0

我有一个很大的 NSDictionary,里面全是 NSData 类型的条目。我有几个条目需要是 int32_t 类型的,但是我不是 100% 确定如何将 NSDictionary 条目中的数据复制到..

是否像执行以下操作一样简单 -

。H

//..
int32_t myint;
}
@property (assign) int32_t myint;
//..

.m

//..
@synthesize cardID;
//..
- (void)assignSearchData:(NSData*)searchData
{
myint = [searchData objectForKey:@"IntKey"];
}
//..

还是我需要在我的方法中进行某种类型的数据转换?

还有一个小问题,我什至正确地声明了 int32_t 吗?我已经在文档和这里寻找了一个例子,但我很难找到一个。

4

2 回答 2

1

好吧,您可以直接访问数据对象中的原始字节。

void const *dataPtr = [data bytes];

现在您有了指向原始内存的指针,您可以随意复制它(这些规则适用于任何数据传输,而不仅仅是 iOS)。如果需要考虑对齐边界,则需要使用 memcpy。

int32_t myInt;
memcpy(&myInt, dataPtr);

否则,如果在允许跨对齐边界进行整数操作的架构上......

int32_t myInt = *(int32_t const *)dataPtr;

现在,ARM 支持跨对齐边界访问,但速度要慢得多。我没有进行性能比较,但是您不会继续使用错误对齐的指针,因此它可能比 memcpy 函数调用更好(不过,老实说,这对您来说可能是太多的性能考虑)。

最大的问题是数据的字节顺序。如果它是由您提供的,那么您可以随心所欲,但您应该更喜欢一种标准。

如果它来自第三方,它可能是网络字节顺序(又名大端)。您可能需要转换为您的主机字节序表示。hton幸运的是,这对和ntoh他们的朋友来说是直截了当的。

FWIW,Intel 是 little-endian,网络字节序是 big-endian,现代 Mac 和 iOS 设备是 little-endian,较旧的 Mac 是 big-endian。

// Convert from network order to host order.
// Does the right thing wherever your code is running
myInt = ntohl(myInt);

简而言之,无论...

int32_t myInt = ntohl(*(int32_t const *)[data bytes]);

或者

int32_t myInt;
memcpy(&myInt, [data bytes);
myInt = ntohl(myInt);

所以,数据必须以某种方式进入那里。是,逆...

int32_t myInt = 42;
myInt = htonl(myInt);
NSData *data = [NSData dataWithBytesNoCopy:&myInt length:sizeof(myInt) freeWhenDone:NO];

当然,使用正确的 Data 初始化器......它只会使用堆栈上的那些原始字节,所以你最好不要在堆栈展开后使用它。

您不必担心发送数据的对齐问题,除非您向接收者保证数据将与某个边界对齐。

于 2012-08-08T23:29:26.630 回答
0

是的,int32_t 很好。所以你有一连串的再见。您需要知道的是他的字节布局是什么。如果您知道数据是什么,那么构建它将非常容易。

给定一个长度为 4(int32_t 大小)的 NSData 对象,那么您将:

int32_t val;
if([data length] == sizeof(uint32_t)) {
    void *bytes = [data bytes];
    // if the layout is same as iOS then
    memcpy(&val, bytes, sizeof(int32_t) );
}

如果不是这种情况,那么您可以尝试:

unsigned char val[4] = {0,0,0,0};
if([data length] == sizeof(uint32_t)) {
    memcpy(val, bytes, sizeof(int32_t) );
    then rearrange the bytes
}
于 2012-08-08T23:06:04.050 回答