2017-01-11 4 views
2

Ich habe den folgenden Code in Objective C geschrieben, dass ich versuche, in Swift 3 zu arbeiten. Einige der Funktionen Äquivalente erscheinen nicht in Swift 3 verfügbar. Hier ist der Code ist der Code in Objective CErhalte Daten von UUID in Swift 3

NSUUID *vendorIdentifier = [[UIDevice currentDevice] identifierForVendor]; 
uuid_t uuid; 
[vendorIdentifier getUUIDBytes:uuid]; 
NSData *vendorData = [NSData dataWithBytes:uuid length:16]; 

und meine aktuelle Anstrengung in Swift 3, die kompiliert und ausgeführt wird, aber nicht die richtige Antwort gibt.

let uuid = UIDevice.current.identifierForVendor?.uuidString 
let uuidData = uuid?.data(using: .utf8) 
let uuidBytes = uuidData?.withUnsafeBytes { UnsafePointer<UInt8>($0) } 
let vendorData : NSData = NSData.init(bytes: uuidBytes, length: 16) 
let hashData = NSMutableData() 
hashData.append(vendorData as Data) 
+0

könnten Sie die Ergebnisse addieren, was Sie erwarten und was Sie von dem schnellen bekommen Code? – muescha

+0

Ich versuche es. Ich mache nicht viel in Objective C. – Andrew

Antwort

4

Die uuid Eigenschaft UUID ist ein C-Array mit Swift importiert wird als Tupel. Mit der Tatsache, dass Swift das Speicherlayout von importierten C Strukturen bewahrt, können Sie einen Zeiger auf das Tupel übergeben zum Data(bytes:, count:) Konstruktor:

if let vendorIdentifier = UIDevice.current.identifierForVendor { 
    var uuid = vendorIdentifier.uuid 
    let data = withUnsafePointer(to: &uuid) { 
     Data(bytes: $0, count: MemoryLayout.size(ofValue: uuid)) 
    } 

    // ... 
} 
+0

Ist es nicht besser, "& uuid.0" zu "& uuid" zu machen? – OOPer

+1

Mit der copy-in/copy-out-Semantik der Swift-inout-Parameter kann Swift eine Region vorbereiten, die nur ein Byte enthalten kann und die Adresse der Region übergeben, wenn Sie '& uuid.0' verwenden. In den meisten Fällen würde '& uuid.0' funktionieren, aber es ist nicht sicher genug. – OOPer

+0

@OOPer: Sie haben Recht, danke für die Rückmeldung! –

3

Hier ist ein möglicher Weg. Beachten Sie, dass identifierForVendor in Swift 3 UUID zurückgibt. UUID hat eine uuid Eigenschaft, die Ihnen eine uuid_t gibt. uuid_t ist ein Tupel von 16 UInt8 Werten.

Der Trick besteht also darin, das Tupel von Bytes in ein Array von Bytes umzuwandeln. Dann ist es einfach, die Data aus dem Array zu erstellen.

if let vendorIdentifier = UIDevice.current.identifierForVendor { 
    let uuid = vendorIdentifier.uuid // gives a uuid_t 
    let uuidBytes = Mirror(reflecting: uuid).children.map({$0.1 as! UInt8}) // converts the tuple into an array 
    let vendorData = Data(bytes: uuidBytes) 
} 

Wenn jemand einen besseren Weg kennt ein Tupel von UInt8 in ein Array von UInt8, bitte sprechen zu konvertieren.

+0

Ich musste Bytes hinzufügen: VendorData = Daten (Bytes: UuidBytes) – Andrew

+0

@Andrew Auf dem Spielplatz brauchte ich nicht die 'Bytes:' Parametername. – rmaddy