Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Data from UUID in Swift 3

I have the following code written in Objective C that I am trying to get working in Swift 3. Some of the functions equivalents do not appear to be available in Swift 3. Here is the code is the code in Objective C

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

and my current effort in Swift 3 which compiles and runs but is not giving the correct answer.

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)
like image 869
Andrew Avatar asked Jan 11 '17 18:01

Andrew


2 Answers

The uuid property of UUID is a C array with is imported to Swift as a tuple. Using the fact that Swift preserves the memory layout of imported C structures, you can pass a pointer to the tuple to the Data(bytes:, count:) constructor:

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

    // ...
}

As of Swift 4.2 (Xcode 10) your don't need to make a mutable copy first:

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

    // ...
}
like image 138
Martin R Avatar answered Nov 15 '22 08:11

Martin R


This extension I made seems to work great without using reflection, nor pointers. It depends on the fact that UUID in Swift is represented as a tuple of 16 UInt8s which can simply be unwrapped like so:

extension UUID{
    public func asUInt8Array() -> [UInt8]{
        let (u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15,u16) = self.uuid
        return [u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15,u16]
    }
    public func asData() -> Data{
        return Data(self.asUInt8Array())
    }
}
like image 42
Dhiraj Gupta Avatar answered Nov 15 '22 06:11

Dhiraj Gupta