为什么NSUserDefaults无法在iPhone SDK中保存NSMutableDictionary?
我想在NSUserDefaults
中保存一个NSMutableDictionary
对象。 NSMutableDictionary
中的密钥类型为NSString
,值类型为NSArray
,其中包含实现NSCoding
的对象列表。根据文件,NSString
和NSArray
均符合NSCoding
。为什么NSUserDefaults无法在iPhone SDK中保存NSMutableDictionary?
我收到此错误:
[NSUserDefaults setObject: forKey:]: Attempt to insert non-property value.... of class NSCFDictionary.
这个任何解决方案?
我发现一个替代方案,在保存之前,我使用NSKeyedArchiver
编码根对象(NSArray
对象),以NSData
结尾。然后使用UserDefaults保存NSData
。
当我需要数据时,我读出NSData
,并使用NSKeyedUnarchiver
将NSData
转换回对象。
这是一个有点麻烦,因为我需要每次转换/从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;
}
任何人都有更好的解决方案吗?
谢谢大家。
是字典中的所有密钥NSString
s?我认为他们必须为了将字典保存到物业清单。
如果要以用户默认值保存对象,则所有对象以递归方式递减,必须是属性列表对象。符合NSCoding并不意味着什么 - NSUserDefaults
不会自动将它们编码为NSData
,您必须自己做。如果你的“实现NSCoding
的对象列表”表示不是属性列表对象的对象,那么在保存为用户默认值之前,你必须对它们做些什么。
供参考的财产清单类NSDictionary
,NSArray
,NSString
,NSDate
,NSData
和NSNumber
。你可以写出可变的子类(如NSMutableDictionary
)给用户的喜好,但你读出的对象将永远是不可变的。
我还应该提到,如果键是NSStrings,NSDictionary只是一个属性列表对象。一般来说,您可以使用其他对象作为字典键,但在需要属性列表的情况下,键必须是字符串。 – 2009-01-23 04:45:32
我遇到了同样的问题,当我想将NSURL作为对象存储在NSDictionary中并将其存储在NSUserDefaults中时。我不得不将它改成NSString,而不是它的工作。 – NicTesla 2011-10-31 09:46:26
太棒了!在我的情况下,我试图使用NSNumber作为用户默认的NSDictionary的关键。我必须将其更改为NSString。 – Joey 2012-05-25 01:40:09
没有更好的解决方案。另一个选择是将编码的对象保存到磁盘 - 但这是做同样的事情。他们最终都会得到NSData,当你想要它时,它会被解码。
您是否考虑过在实施NSCoding
协议?这将允许您使用两种简单的方法在iPhone上进行编码和解码,这些方法使用NSCoding
实现。首先,您需要将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
的两个方法。
我希望这有助于!
简单的答案:
NSDictionary
只是的plist对象,如果键NSString的。 因此,将“钥匙”作为NSString
与stringWithFormat
。
解决方案:
NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];
优点:
- 这将增加字串值。
- 当您的变量值为
NULL
时,它将添加空值。
键是NSString。但值是NSArray,其元素是一个实现NSCoding的定制类。看起来解决方案不工作,因为UserDefaults只支持6种类型,不考虑NSCoding。 – BlueDolphin 2009-01-23 21:11:10