Get Data from UUID in Swift 3
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))
}
// ...
}
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 UInt8
s 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())
}
}
Here's one possible way. Note that identifierForVendor
returns UUID
in Swift 3. UUID
has a uuid
property which gives you a uuid_t
. uuid_t
is a tuple of 16 UInt8
values.
So the trick is converting the tuple of bytes into an array of bytes. Then it's trivial to create the Data
from the array.
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)
}
If anyone knows a better way to convert a tuple of UInt8
into an array of UInt8
, please speak up.