You can convert data.bytes + offset
to a pointer of the
appropriate type and then dereference the pointer:
let dig_x1 = UnsafePointer<Int8>(data.bytes).memory
let dig_y1 = UnsafePointer<Int8>(data.bytes + 1).memory
// ...
let dig_z1 = UnsafePointer<UInt16>(data.bytes + 4).memory
let dig_z2 = UnsafePointer<Int16>(data.bytes + 6).memory
// ...
(Note: Here it is assumed that all values in that binary blob are
property aligned for their type.)
The data is in little-endian byte order, which is also what all
current iOS platforms use. To be on the safe side, convert
the data to host byte order explicitly:
let dig_z1 = UInt16(littleEndian: UnsafePointer(data.bytes + 4).memory)
let dig_z2 = Int16(littleEndian: UnsafePointer(data.bytes + 6).memory)
// ...
An alternative is to define a C structure in the bridging header file
struct MagnetometerData {
int8_t dig_x1;
int8_t dig_y1;
int8_t dig_x2;
int8_t dig_y2;
uint16_t dig_z1;
int16_t dig_z2;
int16_t dig_z3;
int16_t dig_z4;
uint8_t dig_xy1;
int8_t dig_xy2;
uint16_t dig_xyz1;
} ;
and extract the data in one step:
var mdata = MagnetometerData()
data.getBytes(&mdata, length: sizeofValue(mdata))
This works (if there is no padding between the struct members)
because Swift preserves the layout of structures imported from C.
A possible Swift 3 implementation of the first approach is
let dig_x1 = ((data as NSData).bytes).load(as: Int8.self)
let dig_y1 = ((data as NSData).bytes + 1).load(as: Int8.self)
// ...
let dig_z1 = ((data as NSData).bytes + 4).load(as: UInt16.self)
let dig_z2 = ((data as NSData).bytes + 6).load(as: Int16.self)
// ...
Again it is assumed that all values are property aligned for their
type.