为什么NSUserDefaults无法在iOS中保存NSMutableDictionary?
我想在为什么NSUserDefaults无法在iOS中保存NSMutableDictionary?,ios,objective-c,cocoa-touch,nsuserdefaults,nscoding,Ios,Objective C,Cocoa Touch,Nsuserdefaults,Nscoding,我想在NSUserDefaults中保存一个NSMutableDictionary对象。NSMutableDictionary中的键类型是NSString,值类型是NSArray,其中包含实现NSCoding的对象列表。每个文档,NSString和NSArray都符合NSCoding 我得到这个错误: [NSUserDefaults setObject:forKey:]:尝试插入非属性值。。。。属于小说类的 您的所有键都在字典NSStrings中吗?我认为它们必须是这样才能将字典保存到属性列表中
NSUserDefaults
中保存一个NSMutableDictionary
对象。NSMutableDictionary
中的键类型是NSString
,值类型是NSArray
,其中包含实现NSCoding
的对象列表。每个文档,NSString
和NSArray
都符合NSCoding
我得到这个错误:
[NSUserDefaults setObject:forKey:]:尝试插入非属性值。。。。属于小说类的
您的所有键都在字典
NSString
s中吗?我认为它们必须是这样才能将字典保存到属性列表中。如果要以用户默认值保存对象,则所有对象(递归地,一直向下)都必须是属性列表对象。遵守NSCoding在这里并不意味着什么--NSUserDefaults
不会自动将它们编码到NSData
,您必须自己这样做。如果“实现NSCoding
的对象列表”指的是不是属性列表对象的对象,那么在保存为用户默认值之前,您必须对它们进行处理
仅供参考,属性列表类包括
NSDictionary
,NSArray
,NSString
,NSDate
,NSData
和NSNumber
。您可以将可变子类(如NSMutableDictionary
)写入用户首选项,但您读取的对象始终是不可变的。我找到了一个备选方案,在保存之前,我使用NSKeyedArchiver
对根对象(NSArray
对象)进行编码,该编码以NSData
结尾。然后使用UserDefaults保存NSData
需要数据时,我读取NSData
,并使用NSKeyedUnarchiver
将NSData
转换回对象
这有点麻烦,因为我每次都需要转换成NSData,但它可以正常工作
以下是每个请求的一个示例:
保存:
负载:
数组中的元素实现
@interface CommentItem : NSObject<NSCoding> {
NSString *value;
}
谁有更好的解决办法
谢谢大家 没有更好的解决方案。另一种选择是只将编码的对象保存到磁盘上,但这是做同样的事情。它们都以NSData结束,当您想要返回时,它会被解码。您是否考虑过实施
NSCoding
协议?这将允许您使用两种简单的方法在iPhone上进行编码和解码,这两种方法是通过NSCoding
实现的。首先,您需要将NSCoding
添加到类中
以下是一个例子:
这在.h文件中
@interface GameContent : NSObject <NSCoding>
有关更多信息,请查看NSCoder上的文档。这对于我的项目来说非常有用,在我的项目中,如果应用程序关闭,我需要在iPhone上保存应用程序的状态,然后在应用程序重新打开时将其恢复到原来的状态
关键是将协议添加到接口中,然后实现NSCoding
中的两个方法
我希望这有帮助 最简单的答案:
NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];
NSDictionary
仅是plist对象,如果键是NSStrings。
因此,使用stringWithFormat
将键存储为NSString
解决方案:
NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];
好处:
NULL
时,它将添加空值我还应该提到,如果键是NSString,NSDictionary只是一个属性列表对象。通常,您可以使用其他对象作为字典键,但在需要属性列表的情况下,键必须是字符串。当我想将NSURL作为对象存储在NSDictionary中并将其存储在NSUserDefaults中时,遇到了相同的问题。我不得不把它改成一个NSString,然后它就开始工作了。太棒了!在我的例子中,我尝试在用户默认设置中使用NSNumber作为NSDictionary的键。我必须将其转换为NSString。这种迟钝的行为导致没有经验的程序员将整个数据模型写成字典,而不是生成适当的数据对象?对于苹果来说,使用Obj-C有内省和照顾拳击和解体这一事实,对苹果来说是多么可怕的事情,关键是NSCORST。但是值是NSArray,它的元素是一个实现NSCoding的定制类。看来,解决方案不工作,因为用户默认只支持6类类,不考虑NSCODEL。你有一个代码示例,你可以分享,我一直试图做到这一点在邮政(537044),但没有喜悦这对我工作很好。我试图对NSDictionary对象的NSArray进行编码,其中一些键不是字符串。只需在NSArray上使用NSKeyedArchiver和Unarchiver,即可消除“尝试插入非属性值”错误。何时需要释放加载的对象?没有调用alloc,所以我假设它是自动弹性的?我们可能需要添加[defaults synchronize]来保存此处发布的解决方案可能会工作一段时间,但当您决定删除或更改该类时,您会发现自己陷入了混乱。更好的解决方案是让您的对象使用NSNUMBER、字符串等将其状态写入字典,然后将其存储。我有一个类似的问题:我的密钥是NSNumbers,这显然是plist字典密钥中不允许的。
@interface GameContent : NSObject <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"];
}
NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];