2016-09-08 3 views
3

ПОЛУЧИТЬ магнитометр декоративного регистр, как получить NSData(), который выглядит следующим образом:Как конвертировать NSData несколько Ints типа

<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 и конвертировать каждое значение вручную?

ответ

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

(Примечание: Здесь предполагается, что все значения в этом блоб являются свойство выровнены для их type.)

Данные в порядке порядкового числа порядка байтов, что также и все используемые сегодня платформы 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)) 

Это работает (если нет обивки между элементами структуры) , потому что 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) 
// ... 

Опять же, предполагается, что все значения являются собственностью выровнены для их типа.

+0

Большое спасибо! Еще один крошечный вопрос: используя метод, который вы указали z1, оценивается до 22095, является ли это правдоподобным и возможным значением для z1 в регистре дифферента магнитометра? Кроме того, тем не менее это UInt16 или Int16, значение остается неизменным, правильно ли оно? – DCDC

+0

Меня беспокоит, что независимо от того, настроен ли я на UInt16 или Int16, результат тот же, правильно ли это для дополнения двух? – DCDC

+0

@ DCDC: для чисел в диапазоне 0..32767 нет никакой разницы. - Обычно данные датчика необходимо умножить на некоторое число с плавающей запятой, чтобы получить «реальное» значение, которое должно быть документировано для вашего устройства, нет «общей формулы». –

Смежные вопросы