为什么NSUserDefaults无法在iPhone SDK中保存NSMutableDictionary?

我想在NSUserDefaults保存一个NSMutableDictionary对象。 NSMutableDictionary的键types是NSString ,值types是NSArray ,它包含一个实现NSCoding的对象列表。 每个文档, NSStringNSArray都符合NSCoding

我得到这个错误:

[NSUserDefaults setObject:forKey:]:尝试插入NSCFDictionary类的非属性值….

任何解决scheme?

我发现了一个替代scheme,在保存之前,我使用NSKeyedArchiver编码了根对象( NSArray对象),它以NSData结尾。 然后使用UserDefaults保存NSData

当我需要数据时,我读出NSData ,并使用NSKeyedUnarchiverNSData转换回对象。

这有点麻烦,因为我需要每次都转换到/从NSData ,但它只是工作。

以下是每个请求的一个示例:

保存:

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSMutableArray *arr = ... ; // set value NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr]; [defaults setObject:data forKey:@"theKey"]; [defaults synchronize]; 

加载:

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSData *data = [defaults objectForKey:@"theKey"]; NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

数组中的元素实现

 @interface CommentItem : NSObject<NSCoding> { NSString *value; } 

那么在执行CommentItem ,提供了两种方法:

 -(void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeObject:value forKey:@"Value"]; } -(id)initWithCoder:(NSCoder *)decoder { self.value = [decoder decodeObjectForKey:@"Value"]; return self; } 

任何人都有更好的解决

感谢大家。

如果要以用户默认值保存对象,则所有对象以recursion方式一直向下,必须是属性列表对象。 遵从NSCoding并不意味着什么 – NSUserDefaults不会自动将它们编码成NSData ,你必须自己去做。 如果你的“实现NSCoding的对象列表”表示不是属性列表对象的对象,那么在保存到用户默认值之前,你必须对它们做些什么。

FYI属性列表类是NSDictionaryNSArrayNSStringNSDateNSDataNSNumber 。 你可以写可变的子类(如NSMutableDictionary )到用户的喜好,但你读出的对象将永远是不可变的。

你在字典NSString s中的所有密钥? 我认为他们必须把这本字典保存到一份物业清单中。

最简单的答案:

如果键是NSStringsNSDictionary只是一个plist对象 。 因此,将“Key”存储为带有stringWithFormat NSString


解答:

 NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]]; 

好处:

  1. 它会添加string值
  2. 当variables的值为NULL时,它将添加空值

你有没有考虑过实施NSCoding协议? 这将允许您使用NSCoding实现的两个简单的方法在iPhone上进行编码和解码。 首先,您需要将NSCoding添加到您的课程中。

这里是一个例子:

这是在.h文件中

 @interface GameContent : NSObject <NSCoding> 

那么你将需要实现NSCoding协议的两种方法。

  - (id) initWithCoder: (NSCoder *)coder { if (self = [super init]) { [self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]]; } return self; } - (void) encodeWithCoder: (NSCoder *)coder { [coder encodeObject:foundHotSpots forKey:@"foundHotSpots"]; } 

查看NSCoder上的文档以获取更多信息。 对于我需要在iPhone上保存应用程序状态的项目,这真的非常方便,如果应用程序closures了,应用程序closures时恢复到它的状态。

关键是将协议添加到接口,然后实现属于NSCoding的两个方法。

我希望这有帮助!

没有更好的解决scheme。 另一个select是将编码的对象保存到磁盘 – 但这是做同样的事情。 他们最终都会得到解码的NSData,当你想要它回来。