-
-
Save Gernot/604f295786100e7b7b629ea282771889 to your computer and use it in GitHub Desktop.
struct CharacteristicValue { | |
let format: Int8 | |
let exponent: Int8 = -1 | |
let unit: UInt16 | |
let namespace: Int8 | |
let descriptionInfo: Int16 | |
} | |
var value = CharacteristicValue(format: 14, unit: 0x272F, namespace: 1, descriptionInfo: 0) | |
//This works | |
let oldData = NSData(bytes: &value, length: sizeof(CharacteristicValue.self)) | |
//This gives me "Ambiguous Use of 'init'" on the `UnsafePointer` part. | |
let newData = Data(bytes: UnsafePointer<UInt8>(&value), count: sizeof(CharacteristicValue.self)) |
Nice, thanks! I put it into a Data initializer, and now I think I have something that I'm happy with:
extension Data {
init<T>(unsafePointer: UnsafePointer<T>) {
self.init(bytes: UnsafePointer(unsafePointer), count: sizeof(T.self))
}
}
let newData3 = Data(unsafePointer: &value)
assert(newData3 == oldData)
I would use strideof
instead of sizeof
Let me explain why:
Lets say you have a struct:
struct S1{
let a:Int
let b:UInt8
}
sizeof(S1) == 9
strideof(S1)==16
so using sizeof will give you a smaller data which is good. However if you would like to concatenate structs. You have a memory alignment problem (https://en.wikipedia.org/wiki/Data_structure_alignment).
From my current experiences armv7 is not very good at resolving non aligned memory access (and it showed for me only in release mode -> optimisation level -O
). arm64 seems much more stable.
So in your case if you only want to serialse single data structure / struct. It might work fine, but beware of potential memory alignment issues.
Here’s an alternative: wrap the conversion in a function. Then you can call it with
&value
and the compiler will take care of guaranteeing the lifetime of the pointer. I think this reads really nicely: