将NSUUID转换为UnsafePointer <uint8>

时间:2016-10-07 00:28:00

标签: swift3 uuid unsafe-pointers nsuuid

在对Swift 3进行更新后,getUUIDBytes对象上无法显示getBytesUUID

let uuid = UIDevice.current.identifierForVendor
let mutableUUIDData = NSMutableData(length:16)
uuid.getBytes(UnsafeMutablePointer(mutableUUIDData!.mutableBytes))
//   ^^^ compiler error, value of type UUID? has no member getBytes

即使在文档中将getBytes列为UUID上的方法,我也会收到此错误:https://developer.apple.com/reference/foundation/nsuuid/1411420-getbytes

2 个答案:

答案 0 :(得分:3)

一种正确的方式:

let uuid = UIDevice.current.identifierForVendor!
var rawUuid = uuid.uuid

withUnsafePointer(to: &rawUuid) {rawUuidPtr in //<- `rawUuidPtr` is of type `UnsafePointer<uuid_t>`.
    rawUuidPtr.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout<uuid_t>.size) {bytes in
        //Use `bytes` only in this closure. (Do NEVER export `bytes` out of the closure.)
        print(bytes[0],bytes[1])
        //...
    }
}

另一种正确的方式:

withUnsafePointer(to: &rawUuid) {rawUuidPtr in //<- `rawUuidPtr` is of type `UnsafePointer<uuid_t>`.
    let bytes = UnsafeRawPointer(rawUuidPtr).assumingMemoryBound(to: UInt8.self)
    //Use `bytes` only in this closure. (Do NEVER export `bytes` out of the closure.)
    print(bytes[0],bytes[1])
    //...
}

正如Rob已经评论过的那样,导出传递给withUnsafeBytes的闭包参数的指针完全无法保证。稍微改变一下上下文(32位/ 64位,x86 / ARM,调试/发布,添加看似无关的代码......)会让你的应用程序变得更糟糕。

另一个重要的事情是Data的UTF-8 uuidStringNSUUID.getBytes的字节序列完全不同:

let nsUuid = uuid as NSUUID //<-Using the same `UUID`

let mutableUUIDData = NSMutableData(length:16)!
nsUuid.getBytes(mutableUUIDData.mutableBytes.assumingMemoryBound(to: UInt8.self))
print(mutableUUIDData) //-><1682ed24 09224178 a279b44b 5a4944f4>

let uuidData = uuid.uuidString.data(using: .utf8)!
print(uuidData as NSData) //-><31363832 45443234 2d303932 322d3431 37382d41 3237392d 42343442 35413439 34344634>

答案 1 :(得分:3)

你的想法太复杂了:

client.UsingCommands(input => { 
  input.PrefixChar = '!';
  input.AllowMentionPrefix = true;
});

command = client.GetService<CommandService>();

command.CreateCommand("echo").Parameter("param", ParameterType.Multiple).Do(async (e) => {
  var channel = e.Server.FindChannels(e.Message.Channel.Name, ChannelType.Text).FirstOrDefault();
  string msg = "";
  for (int i = 0; i < e.Args.Length; i++) {
    msg += e.Args[i] + " ";
  }
  msg = msg.Remove(msg.Length - 1);
  await channel.SendMessage(msg);
});

为什么这样做?

考虑一下:

func getUUID ( ) -> Data {
    let uuid = NSUUID()
    var bytes = [UInt8](repeating: 0, count: 16)
    uuid.getBytes(&bytes)
    return Data(bytes: bytes)
}

然后你可以这样做:

func printInt(atAddress p: UnsafeMutablePointer<Int>) {
    print(p.pointee)
}

但你也可以这样做:

var value: Int = 23
printInt(atAddress: &value)
// Prints "23"

这是一种隐含的桥接&#34;形式。引用Swiftdoc.org

  

隐式创建指向数组元素的可变指针   当您使用inout语法传递数组时。

此隐式桥接仅保证有效指针,直到当前函数返回。这样的指针绝对不能逃脱&#34;当前函数上下文,但使用它们作为inout参数总是安全的,因为inout参数始终只保证在被调用函数返回之前有效,并且被调用函数必须在当前参数之前返回,所以这不会出错。 / p>

对于那些不了解的人,将var numbers = [5, 10, 15, 20] printInt(atAddress: &numbers) // Prints "5" 投放到UUIDNSUUID),反过来(... as NSUUID)保证永远成功。但如果你坚持使用... as UUID,最简单的方法是:

UUID