I’ve written articles1 on getting raw data into Swift types. This can happen when reading data from a device using Core Bluetooth. Writing data to a Bluetooth Device requires going the other direction and turning your numbers or arrays into raw Data. Luckily, going to Data is a bit easier.
The Data()
constructor takes a Sequence. A type of UnsafeRawBufferPointer
provides a Sequence interface to iterate over the bytes as UInt8
. Creating a Data
representation is a matter of getting an UnsafeRawBufferPointer
.2
If you have a single scalar, there is a global function withUnsafeBytes(of: body:)
that presents a closure
var i: Int32 = 500 // must be a var to pass as inout parameter let data = withUnsafeBytes(of: &i) { (ptr) -> Data in // ptr is an UnsafeRawBufferPointer, which is a Collection return Data(ptr) }
Arrays have an instance method to access the bytes:
let array: [UInt32] = [1, 2, 3] let data = array.withUnsafeBytes { (ptr) -> Data in return Data(ptr) }
Make sure to use the correct width (8 bit, 16 bit, 32 bit) based on what the device is expecting on the other side. Using Int
will usually get you 64-bit Integers, but not always. It’s best to be explicit when a specific width is necessary.
As always when dealing with network communication, you might need to switch endianness for the device on the other side.
let myArray : [UInt32] = [1, 2, 3] let bigEndianArray = myArray.map() { $0.bigEndian } let bigEndianData = bigEndianArray.withUnsafeBytes { (ptr) in ptr.map return Data(ptr) }
-
See: Turning Data Into Arrays In Swift and Turning Data Into Numbers in Swift ↩
-
There are other paths to the same route, like getting an
UnsafeBufferPointer<T>
to pass toData(buffer:)
. ↩