有什么方法可以使用NSKeyedArchiver
来编码包含自定义结构的NSValue
?我有一个NSDictionary
,其中包含NSValues
中包含的结构,我想将其存档为更大的对象图的一部分但我收到以下错误:
-[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs
但是,请考虑以下事项:
//Copy of the CGPoint declaration
struct MYPoint {
CGFloat x;
CGFloat y;
};
typedef struct MYPoint MYPoint;
CGPoint point = {1.0, 1.0};
MYPoint myPoint = {1.0, 1.0};
NSLog(@"CGPoint: %s", @encode(CGPoint)); //CGPoint: {CGPoint=ff}
NSLog(@"MYPoint: %s", @encode(MYPoint)); //MYPoint: {MYPoint=ff}
NSValue *CGPointValue = [NSValue valueWithBytes:&point objCType:@encode(CGPoint)];
NSData *CGPointData = [NSKeyedArchiver archivedDataWithRootObject:CGPointValue];
//NO ERROR
NSValue *MYPointValue = [NSValue valueWithBytes:&myPoint objCType:@encode(MYPoint)];
NSData *MYPointData = [NSKeyedArchiver archivedDataWithRootObject:MYPointValue];
//ERROR: -[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs
是否只是“此归档程序无法编码您的结构”,这就是故事的结尾,或者是否可能获得与{{{ 1}}但是对于自定义结构?
我可能只是创建一个包含CGPoint
并实现NSValue
的小型自定义对象来解决它,但我对上面代码中NSCoding
所显示的矛盾感到好奇。并想知道是否有办法扩展NSValue以获得相同的行为。
答案 0 :(得分:1)
有些问题与@encode
和匿名结构有关。尝试将结构定义更改为:
typedef struct MYPoint {
CGFloat x;
CGFloat y;
} MYPoint;
如果这不起作用,您可以使用NSData
包装结构:
[NSData dataWithBytes:&myPoint length:sizeof(MYPoint)];
答案 1 :(得分:0)
以下示例说明了对自定义C结构的编码。
//assume ImaginaryNumber defined:
typedef struct {
float real;
float imaginary;
} ImaginaryNumber;
ImaginaryNumber miNumber;
miNumber.real = 1.1;
miNumber.imaginary = 1.41;
NSValue *miValue = [NSValue valueWithBytes: &miNumber withObjCType:@encode(ImaginaryNumber)];
ImaginaryNumber
miNumber2;
[miValue getValue:&miNumber2
];
您指定的类型必须是恒定长度。您不能在NSValue中存储C字符串,可变长度数组和结构以及其他不确定长度的数据类型 - 您应该为这些类型使用NSString或NSData对象。您可以在NSValue对象中存储指向可变长度项的指针。以下代码摘录错误地尝试将C字符串直接放入NSValue对象中:
/* INCORRECT! */
char *myCString = "This is a string.";
NSValue *theValue = [NSValue valueWithBytes:myCString withObjCType:@encode(char *)];
在此代码摘录中,myCString的内容被解释为指向char的指针,因此字符串中包含的前四个字节被视为指针(实际使用的字节数可能因硬件架构而异)。也就是说,序列“This”被解释为指针值,它不太可能是合法地址。存储此类数据项的正确方法是使用NSString对象(如果需要包含对象中的字符),或者传递其指针的地址,而不是指针本身:
/* Correct. */
char *myCString = "This is a string.";
NSValue *theValue = [NSValue valueWithBytes:&myCString withObjCType:@encode(char **)];
此处传递myCString的地址(& myCString),因此字符串的第一个字符的地址存储在theValue中。
重要说明:NSValue对象不会复制字符串的内容,而是复制指针本身。如果使用分配的数据项创建NSValue对象,则在NSValue对象存在时不要释放数据的内存。