2016-10-07 2 views

答えて

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]) 
    //... 
} 

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のメソッドとしてリストされていても、このエラーが出ます


Robによって既にコメントされているように、クロージャの引数withUnsafeBytesに渡されたポインタのエクスポートは完全に保証されていません。コンテキスト(32ビット/ 64ビット、x86/ARM、デバッグ/リリース、一見無関係なコードを追加...)の少しの変更は、あなたのアプリをクラッシャーにするでしょう。

そして、もう一つ重要なことは、UTF-8 uuidStringDataNSUUID.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> 
+0

私は3 'Data'はその'私は順番にSHA1_Update' 'に渡す必要bytes'をvarsの持っている、そして、あなたの入力を取得したいのですが。推奨フローは本当に 'withUnsafeBytes'の3つのネストされたブロックを持っていますか? – ray

+0

@rayは、Swift 3の 'Data'を使って作業しているときに正しい方法であると思われます。そうでない場合は' Unsafe [Mutable] Pointer'を使うことができます。誰か(Appleの開発フォーラムのAppleのスタッフ)は、C/Objective-CにもっとSwiftyラッパーを書くことを提案しています。 – OOPer

3

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" 

をしかし、あなたもこれを行うことができます。

var numbers = [5, 10, 15, 20] 
printInt(atAddress: &numbers) 
// Prints "5" 

それは暗黙の「の形だがブリッジング "。 Swiftdoc.orgから引用すると:あなたは構文inoutの使用して配列を渡すとき

を配列の要素への変更可能なポインタが暗黙のうちに が作成されます。

この暗黙的なブリッジは、現在の関数が返るまで有効なポインタのみを保証します。このようなポインタは、現在の関数コンテキストを "エスケープ"してはいけませんが、inout引数は、呼び出された関数が返って呼び出される関数が現在の関数よりも前に返されるまで、これは間違っていることはできません。

そして、知らないもののために、NSUUIDUUID... as NSUUID)をキャストし、他の方法ラウンド(... as UUID)は常に成功することが保証されています。しかし、あなたはUUIDを使う、という場合は、最も簡単な方法は次のとおりです。

private 
func getUUID () -> Data { 
    var uuid = UUID().uuid 
    return withUnsafePointer(to: &uuid) { 
     return Data(bytes: $0, count: MemoryLayout.size(ofValue: uuid)) 
    } 
} 
+0

非常に簡単です。そしてそれは動作します! – davidgyoung

関連する問題