2016-10-07 2 views
2

Nach dem Update auf Swift 3 werden getUUIDBytes und getBytes nicht auf dem Objekt UUID angezeigt.NSUUID in unsafePointer konvertieren <UInt8>

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 

ich diesen Fehler auch bei getBytes als Methode auf UUID in der Dokumentation aufgeführt ist: https://developer.apple.com/reference/foundation/nsuuid/1411420-getbytes

Antwort

3

Ein richtiger Weg:

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

Ein weiterer richtiger Weg:

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

Wie bereits von Rob kommentiert, ist der Export des an das Closure-Argument übergebenen Zeigers withUnsafeBytes absolut NICHT garantiert. Eine geringfügige Änderung des Kontexts (32-Bit/64-Bit, x86/ARM, Debug/Release, Hinzufügen von scheinbar nicht verwandtem Code ...) würde Ihre App zum Absturz bringen.

Und noch eine wichtige Sache ist, dass UTF-8 Data des uuidString und die Byte-Reihenfolge von NSUUID.getBytes völlig unterschiedlich sind:

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

Ich mag würde Ihre Eingabe dann bekommen, habe ich 3 'Data' Vars dessen' bytes' ich 'SHA1_Update' nacheinander passieren müssen .Ist der empfohlene Fluss wirklich 3 verschachtelte Blöcke von 'withUnsafeBytes'? – ray

+0

@ray, scheint das der richtige Weg zu sein, wenn man in Swift 3 mit 'Data' arbeitet. Oder man kann mit' Unsafe [Mutable] Pointer' arbeiten. Jemand (Apples Mitarbeiter im Dev-Forum von Apple) hat vorgeschlagen, in C/Objective-C einen Swifty-Wrapper zu schreiben. – OOPer

3

Sie denken zu kompliziert:

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

Warum diese Arbeit?

Betrachten Sie haben:

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

dann können Sie in der Tat dies tun:

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

aber Sie können dies auch tun:

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

Es ist eine Form der „impliziten ist Überbrückung". Zitat aus Swiftdoc.org:

Ein wandelbaren Zeiger auf die Elemente eines Arrays implizit erstellt, wenn Sie das Array mit inout Syntax übergeben.

Diese implizite Überbrückung garantiert nur gültige Zeiger, bis die aktuelle Funktion zurückkehrt. Solche Zeiger dürfen niemals den aktuellen Funktionskontext "verlassen", aber sie als inout-Argument zu verwenden ist immer sicher, da inout-Argumente immer nur gültig sind, bis die aufgerufene Funktion zurückkehrt und die aufgerufene Funktion vor dem aktuellen zurückkehren muss. Das kann also nicht schiefgehen.

Und für diejenigen, die nicht wissen, Gießen UUID zu NSUUID (... as NSUUID) und umgekehrt (... as UUID) immer gelingt garantiert. Aber wenn Sie darauf bestehen, UUID verwenden, ist der einfachste Weg:

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

Sehr einfach. Und es funktioniert! – davidgyoung

Verwandte Themen