2013-04-23 104 views
3

我想一个数组保存到NSUserDefaults。 我读到我必须使用一个编码器和解码器,但我仍然得到同样的错误保存的NSMutableArray NSUserDefaults的到

*** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '(
    "<Item: 0x1e86e380>", 
    "<Item: 0x1e86fd60>", 
    "<Item: 0x1e86fda0>", 
    "<Item: 0x1e86fde0>", 
    "<Item: 0x1e86fe10>" 
)' of class '__NSArrayM'. Note that dictionaries and arrays in property lists must also contain only property values. 
[unknown][unknown][unknown][unknown][unknown](gdb) 

为什么?

这里是我的代码:

这是我的模型。它有NSStringsNSNumbersNSMutableArrays

- (void)encodeWithCoder:(NSCoder *)encoder 
{ 
    [encoder encodeObject: self.title forKey:@"title"]; 
    [encoder encodeObject: self.desc forKey:@"desc"]; 
    [encoder encodeObject: (NSNumber*) self.day forKey:@"day"]; 
    [encoder encodeObject: self.images forKey:@"images"]; 
} 

- (id)initWithCoder:(NSCoder *)decoder 
{ 
    self = [super init]; 
    if(self != nil) 
    { 
     self.title = [decoder decodeObjectForKey: @"title"]; 
     self.desc = [decoder decodeObjectForKey: @"desc"]; 
     self.day = [decoder decodeObjectForKey: @"day"]; 
     self.images = [decoder decodeObjectForKey: @"images"]; 

    } 
    return self; 
} 

这是在AppDelegate中的DidFinishLaunching方法:

if([[NSUserDefaults standardUserDefaults] objectForKey:@"savedData"] == nil) 
{ 
    items = [[NSMutableArray alloc] init]; 

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"items" ofType:@"json"]; 
    NSString *contents = [NSString stringWithContentsOfFile: filePath encoding: NSUTF8StringEncoding error: nil]; 
    SBJsonParser *jsonParser = [[SBJsonParser alloc] init]; 
    NSMutableDictionary *json = [jsonParser objectWithString: contents]; 
    jsonParser = nil; 
    items = json[@"item"]; 

    for(NSDictionary *itemDict in items) 
    { 

     Item *item = [[Item alloc] init]; 

     item.title = [itemDict valueForKey:@"title"]; 
     item.desc = [itemDict valueForKey:@"description"]; 
     item.day = [itemDict valueForKey:@"day"]; 
     item.images = [itemDict valueForKey: @"images"]; 

     [items addObject: item]; 

    }  
} 
else 
{ 

    NSData *decodedObject = [userDefault objectForKey: [NSString stringWithFormat:@"savedData"]]; 
    NSArray *decodedArray =[NSKeyedUnarchiver unarchiveObjectWithData: decodedObject]; 


    items = [decodedArray mutableCopy]; 

} 

这个我有AppWillTerminate

userDefault = [NSUserDefaults standardUserDefaults]; 
    NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject: items]; 
    [userDefault setObject: encodedObject forKey:[NSString stringWithFormat:@"savedData"]]; 
+0

我不认为这个异常来源于你所示的代码。在Xcode中添加一个异常断点。我怀疑你在项目的其他地方使用了'setObject:forKey:'和'Item'(非属性列表对象)。 – omz 2013-04-23 13:18:31

+0

是的。当我删除代码中的错误消失.. – Jojo 2013-04-23 13:37:20

+0

只能存储内置的对象类型值NSUserDefault,如果你试图存储自定义(用户定义的对象),它会产生错误,所以请存储内置在对象 – 2013-04-23 16:52:25

回答

1

引言:了解用户的默认值不是通用数据库。除非您建议在那里存储的数据非常少,否则我强烈建议您不要这样做。另一种方法是将数据存储在定义明确的位置,例如应用程序支持目录。

编辑

在前款规定的,我曾经指出,应用程序支持目录不应该被用于将改变的数据。我找不到任何支持这一点的东西。苹果自己的文档指出它是“在您的应用程序商店,支持应用程序,但在应用程序运行不是必需的,任何类型的文件的”用户数据不应该被存储在那里,而且每个应用程序应该创建和维护自己的目录里面,而不是写到它的顶层。根本不确定我在哪里捡到了这部小说,并且很抱歉让它永久存在。

编辑完

话虽这么说,当编译器“非财产值(S)”的抱怨,意味着你试图写一些东西,是不是NSArray,NSDictionary,NSString,NSData,NSDateNSNumber.

你是正确的,你自己的对象需要使用的NSKeyedArchiver和NSKeyedUnarchiver的。但是,仅仅因为你在你的模型对象实现您NSCoding方法不会改变一个事实,即它不是一个属性列表值。

您需要做的是在之前使用NSKeyedArchiver您尝试存储每个对象。这产生了一个NSData的实例,它可以作为属性列表对象存储。

+0

你为什么会避免应用程序支持文件夹? – omz 2013-04-23 13:25:42