如何将NSData转换为多个类型Ints

时间:2016-09-08 11:53:28

标签: ios swift nsdata

我获得磁力计调整寄存器作为获取NSData(),如下所示:

<00001a1a 4f56f202 00000000 1dfd421b>

我需要将其转换为Int8,UInt8,Int16,UInt16,具体取决于我访问的字节。

来自文档的来源:

s8 dig_x1;/**< trim x1 data */
s8 dig_y1;/**< trim y1 data */

s8 dig_x2;/**< trim x2 data */
s8 dig_y2;/**< trim y2 data */

u16 dig_z1;/**< trim z1 data */
s16 dig_z2;/**< trim z2 data */
s16 dig_z3;/**< trim z3 data */
s16 dig_z4;/**< trim z4 data */

u8 dig_xy1;/**< trim xy1 data */
s8 dig_xy2;/**< trim xy2 data */

u16 dig_xyz1;/**< trim xyz1 data *

enter image description here

主要问题是如何访问NSData中的选定字节以手动将其转换为Int8或UIint16等?

一般来说,如何处理这样的问题?应该寻找一种手动迭代NSData并手动转换每个值的方法吗?

1 个答案:

答案 0 :(得分:4)

您可以将data.bytes + offset转换为指针 适当的类型,然后取消引用指针:

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
// ...

(注意:这里假设该二进制blob中的所有值都是 属性与其类型一致。)

数据是以little-endian字节顺序排列的,这也是全部 目前的iOS平台使用。为了安全起见,转换 显式主机字节顺序的数据:

let dig_z1 = UInt16(littleEndian: UnsafePointer(data.bytes + 4).memory)
let dig_z2 = Int16(littleEndian: UnsafePointer(data.bytes + 6).memory)
// ...

另一种方法是在桥接头文件中定义C结构

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;
} ;

并一步提取数据:

var mdata = MagnetometerData()
data.getBytes(&mdata, length: sizeofValue(mdata))

这是有效的(如果struct成员之间没有填充) 因为Swift 保留从C导入的结构的布局。

第一种方法可能的 Swift 3 实施

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) 
// ...

再次假设所有值都是属性对齐的 类型。