如何将NSValue转换为NSData并返回? [英] How to convert NSValue to NSData and back?
问题描述
A有一些NSValue
(通过KVC valueForKey
获取),我需要将其附加到NSData
对象,以便使用Game Center通过网络发送它.显然,我还需要将NSValue
从NSData
转换回更多的KVC(setValue:forKey:
).
A have a number of NSValue
(obtained via KVC valueForKey
) that I need to append to an NSData
object in order to send it over the network using Game Center. Obviously I will also need to convert the NSValue
back from NSData
for more KVC (setValue:forKey:
).
我不知道每个NSValue
的确切类型,所以我仅限于使用NSValue
和NSData
提供的接口.我应该提到NSValue
绝不是指针类型.
I don't know the exact type of each NSValue
, so I'm limited to using the interfaces provided by NSValue
and NSData
. I should mention that the NSValue
are never pointer types.
我很惊讶没有[NSData dataWithValue:value]
,也没有类似[value dataWithEncoding:]
之类的东西.但是也许我是盲人,没有看到明显的选择.我曾考虑过使用getValue:
将值复制到void*
缓冲区中,但是除了使用objCType
并将其与所有可能的类型进行比较之外,我应该如何确定缓冲区的长度?
I'm surprised that there's no [NSData dataWithValue:value]
and neither something like [value dataWithEncoding:]
or similar. But maybe I'm blind and not seeing the obvious choice. I thought about using getValue:
to copy the value into a void*
buffer, but how am I supposed to determine the buffer length other than by using objCType
and comparing that with all possible types?
我应该怎么做?
注意:
NSKeyedArchiver
毫无疑问,因为它效率极低.将4字节的浮点型归档为142字节的NSData
,将8字节的CGPoint
归档为NSData
时使用260字节.保持发送的数据量最少对我正在做的事情至关重要.
NOTE:
NSKeyedArchiver
is out of the question because it is terribly inefficient. A 4 Byte float is archived to a 142 Bytes NSData
, a 8 Byte CGPoint
uses 260 Bytes when archived to NSData
. Keeping the amount of data sent to a minimum is crucial to what I'm doing.
推荐答案
Martin Gordon的答案越来越近了,但是幸运的是,您不必手动解析objCType字符串.有一个功能可以做到:这个问题引导我解决问题.
Martin Gordon's answer is getting close, but fortunately you don't have to manually parse the objCType string. There's a function that does that: NSGetSizeAndAlignment. From that you get the size/length of the value obtained from getValue:. This question lead me to the solution.
我最终为NSData创建了一个类别,该类别使我可以从NSNumber或NSValue对象创建NSData:
I ended up creating a category for NSData that allows me to create NSData from NSNumber or NSValue objects:
@interface NSData (GameKitCategory)
+(NSData*) dataWithValue:(NSValue*)value;
+(NSData*) dataWithNumber:(NSNumber*)number;
@end
@implementation NSData (GameKitCategory)
+(NSData*) dataWithValue:(NSValue*)value
{
NSUInteger size;
const char* encoding = [value objCType];
NSGetSizeAndAlignment(encoding, &size, NULL);
void* ptr = malloc(size);
[value getValue:ptr];
NSData* data = [NSData dataWithBytes:ptr length:size];
free(ptr);
return data;
}
+(NSData*) dataWithNumber:(NSNumber*)number
{
return [NSData dataWithValue:(NSValue*)number];
}
@end
我还在此NSValue/NSNumber数据之前添加了一个小标头,该标头使我可以解码该数据所针对的属性以及数据部分中的字节数.这样,我可以将值恢复到remote属性.
I also add a small header before this NSValue/NSNumber data that allows me to decode which property the data is for and how many bytes are in the data section. With that I can restore the value to the remote property.
这篇关于如何将NSValue转换为NSData并返回?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!