我在NSUserDefaults结构NSMutableArray错了吗? “尝试插入非属性列表对象”

我很简单地试图保存在NSUserDefaultsstruct s的NSMutableArray / NSArray

 typedef struct { int key; } provision; provision p1; p1.key = 4; NSValue *p1Value = [NSValue value:&p1 withObjCType:@encode(provision)]; provision p2; p2.key = 5; NSValue *p2Value = [NSValue value:&p2 withObjCType:@encode(provision)]; NSMutableArray *provisions = [[NSMutableArray alloc] init]; [provisions addObject:p1Value]; [provisions addObject:p2Value]; [[NSUserDefaults standardUserDefaults] setObject:provisions forKey:@"Provisions"]; 

我按照这里的指南 ,把所有的结构存储为NSValue 。 但是最后一行会导致运行时错误:

*由于未捕获的exception'NSInvalidArgumentException',原因:'* – [NSUserDefaults setObject:forKey:]:试图为键“Provisions”插入非属性列表对象(“<04000000>”,“<05000000>”)

我究竟做错了什么?

从NSUserDefaults类参考 :

一个默认对象必须是一个属性列表,也就是一个实例(或集合的实例组合): NSDataNSStringNSNumberNSDateNSArrayNSDictionary 。 如果要存储任何其他types的对象,则通常应将其存档以创build一个NSData实例。

发生exception是因为您尝试存储一个NSValue对象。 要将结构存储NSData ,请使用

 NSData *p1data = [NSData dataWithBytes:&p1 length:sizeof(p1)]; 

并从NSData 提取

 [p1data getBytes:&p1 length:sizeof(p1)]; 

你真的需要使用一个结构? 如果没有,使用类而不是结构会更好。 或者你甚至可以创build一个类来包装你的结构。 对我来说,这似乎比你想要做的更清楚(因此不太容易犯错误)。 无论如何,你也可以像Martin R所说的那样做。

注意 :正如MartinR在他对我的回答的评论中指出的那样,您还需要NSData将自定义对象添加到NSUserDefaults。