为什么 NSSUserDefault 未能在 iOS 中保存 NSMutableDictionary?

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

我得到了这个错误:

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

76952 次浏览

你所有的钥匙都在字典 NSString里吗?我认为它们必须是为了将字典保存到一个属性列表中。

如果以用户默认值保存对象,则所有对象(一直递归地)都必须是属性列表对象。符合 NSCoding 在这里没有任何意义—— NSUserDefaults不会自动将它们编码到 NSData中,您必须自己这样做。如果“实现 NSCoding的对象列表”指的是不是属性列表对象的对象,那么在保存为用户默认值之前,必须对它们进行一些处理。

仅供参考,属性列表类是 NSDictionaryNSArrayNSStringNSDateNSDataNSNumber。您可以将可变的子类(如 NSMutableDictionary)写入用户首选项,但是您读出的对象将始终是不可变的。

我发现了一种替代方法,在保存之前,我使用 NSKeyedArchiver对根对象(NSArray对象)进行编码,NSKeyedArchiverNSData结束。然后使用 UserDefault 保存 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;
}

有人有更好的解决办法吗?

谢谢大家。

没有更好的解决办法了。另一种选择是将编码后的对象保存到磁盘上——但这也是一样的做法。它们最终都会在你想要回 NSData 的时候被解码。

你是否考虑过实施 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 上保存应用程序的状态,并在应用程序重新启动时将其恢复到原来的状态,这对我的项目来说非常方便。

关键是向接口添加协议,然后实现作为 NSCoding一部分的两个方法。

希望这个能帮上忙!

最简单的回答:

如果 键是 NSString。 因此,将 “钥匙”存储为 NSStringstringWithFormat


解决方案:

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

好处:

  1. 它将添加 字符串-值
  2. 当变量值为 NULL时,它将添加 空值