2014-09-02 103 views
13

我无法在NsUserDefaults中存储NSArray。该应用程序获取此行 [savedData setObject:jsonValue forKey:@"JSONDATA"];将NSArray存储在NSUserDefaults中时应用程序崩溃

下面是我的代码崩溃
。和我提以下

NSArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
[savedData setObject:jsonValue forKey:@"JSONDATA"]; 
[savedData synchronize]; 

错误日志我的日志错误:

*** Terminating app due to uncaught exception '`NSInvalidArgumentException`', reason: '*** - 

[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object <CFBasicHash 0x8c62b10 [0x1d2aec8]>{type = immutable dict, count = 3, 
    entries => 
+0

可以检查jsonValue的内容? – 2014-09-02 06:49:07

+0

我认为这是你要找的东西: http://stackoverflow.com/questions/19720611/attempt-to-set-a-non-property-list-object-as-an-nsuserdefaults# 19720674 – grimdox 2014-09-02 06:54:25

+0

请NSLog您尝试存储的值。我们所拥有的只是一个错误信息,在事情变得有趣之前就被切断了。 – gnasher729 2014-09-02 07:18:21

回答

42

是的,他们不能像这样保存在NSUserDefaults

我在下面写一个代码,请看看和更多的研究去看看苹果文档好吧。

代码是在这里:

//救国

NSData *dataSave = [NSKeyedArchiver archivedDataWithRootObject:yourArrayToBeSave]]; 
[[NSUserDefaults standardUserDefaults] setObject:dataSave forKey:@"array"]; 

[[NSUserDefaults standardUserDefaults] synchronize]; // this will save you UserDefaults 

//用于检索

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"array"]; 
NSArray *savedArray = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
+0

为什么要将NSData转换为NSArray并返回到NSData? – gnasher729 2014-09-02 07:27:00

+0

@ gnasher729请参阅问题......“yourArrayToBeSaved”非财产清单对象这就是为什么它不能的NSArray的变化保存到NSUserDefaults的,因此,以NSData的和背部 – 2015-01-13 20:45:20

+0

是的,我用这个,但应用程序崩溃。 – 2017-08-11 07:51:08

0

您需要首先分配的NSArray,那么你可以通过在数组中的值。你不能直接传递价值。 NSArray * a = [[NSArray alloc] initWithObjects:[NSJSONSerialization JSONObjectWithData:data options:0 error:nil],nil];

+1

这是无稽之谈。将JSON对象放入数组不会使其成为属性列表对象。 – gnasher729 2014-09-02 07:17:40

1

我觉得jsonValue是的NSDictionary的NSArray不..

id jsonValue = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; 
    if ([jsonValue isKindOfClass:[NSDictionary class]]) 
    { 
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue]; 
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"]; 
    [savedData synchronize]; 
    } 

//(OR)

NSDictionary *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue]; 
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"]; 
[savedData synchronize]; 

此外我认为你不能在NSDictionary的直接存储到NSUserDefaults..Go通过@kshitij godara把它做/保存..

您可以使用NSKeyedArchiver将您的字典写出到NSData。

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue]; 
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"]; 

用于检索数据:

NSData *dictionaryData = [defaults objectForKey:@"JSONDATA"]; 
NSDictionary *dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:dictionaryData]; 

希望这有助于你..!

+1

您从NSData开始。您将NSData转换为字典或数组。您将字典或数组转换为NSData并存储它。你能看到代码中的两个完全无意义的步骤吗? – gnasher729 2014-09-02 07:23:59

3

虽然kshitij的回答是正确的,可悲的是,它并没有在那里结束。如果您想要将自定义对象保存在您的NSUserDefaults中,则您的自定义对象必须实施NSCoding协议并覆盖initWithCoderencodeWithCoder方法。这样的一个例子如:

@interface Book : NSObject <NSCoding> 
@property NSString *title; 
@property NSString *author; 
@property NSUInteger pageCount; 
@property NSSet *categories; 
@property (getter = isAvailable) BOOL available; 
@end 

@implementation Book 

#pragma mark - NSCoding 

    - (id)initWithCoder:(NSCoder *)decoder { 
     self = [super init]; 
     if (!self) { 
      return nil; 
     } 

     self.title = [decoder decodeObjectForKey:@"title"]; 
     self.author = [decoder decodeObjectForKey:@"author"]; 
     self.pageCount = [decoder decodeIntegerForKey:@"pageCount"]; 
     self.categories = [decoder decodeObjectForKey:@"categories"]; 
     self.available = [decoder decodeBoolForKey:@"available"]; 

     return self; 
    } 

    - (void)encodeWithCoder:(NSCoder *)encoder { 
     [encoder encodeObject:self.title forKey:@"title"]; 
     [encoder encodeObject:self.author forKey:@"author"]; 
     [encoder encodeInteger:self.pageCount forKey:@"pageCount"]; 
     [encoder encodeObject:self.categories forKey:@"categories"]; 
     [encoder encodeBool:[self isAvailable] forKey:@"available"]; 
    } 

@end 
1

尝试这样

NSMutableArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
    NSData *yourEncodedObject = [NSKeyedArchiver archivedDataWithRootObject: jsonValue]; 

     NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
     [userData setObject: yourEncodedObject forKey:@"JSONDATA"]; 
    [savedData synchronize]; 
+0

你可以告诉你的JSON数据,什么是NSArray中* jsonValue? – Sport 2014-09-02 06:59:52

1

接受NSUserDefaults的属性列表对象 - 的NSDictionary,NSArray中,的NSString,NSNumber的,NSDate的和NSData的。JSON文档包含NSDictionary,NSArray,NSString,NSNumber和NSNull。您会看到差异 - 属性列表对象不能包含NSNull值。

如果你的JSON对象包含NSNull对象(即您解析包含一个“空”值的JSON文件),那么你就无法将其保存到NSUserDefaults的。除此之外,所有评论说你不能存储JSON数据在NSUserDefaults是无稽之谈。只有NSNull对象导致问题。

有一个非常,非常简单的解决您的问题。只需将原始json数据作为NSData对象存储在NSUserDefaults中即可。然后当你阅读NSUserDefaults时,你会得到NSData并解析它们。取而代之的

NSArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
[savedData setObject:jsonValue forKey:@"JSONDATA"]; 
[savedData synchronize]; 

你只写

NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
[savedData setObject:data forKey:@"JSONDATA"]; 
[savedData synchronize]; 
+0

显然是最好的答案。 – 2017-01-08 09:34:57

0

NSUserDefaults的应该只能用于多达500K的数据(https://forums.developer.apple.com/message/50696#50696

如果存储更大量的应用程序可能会崩溃,从个人的经验,我”已经看到的应用程序存储数据的在1MB /后不久[NSUserDefaults的的setObject:]崩溃和[同步NSUserDefaults的]。

要检查的现场应用多少数据使用,开放的Xcode - >窗口 - >设备,选择您的设备,在安装应用程序中选择您的应用程序和下载应用程序容器。默认存储在AppData->首选项> your.app.plist

将数据保存到用户默认另一种方法是写入文件:

-(void)saveObject:(NSObject *)object toFile:(NSString *)name { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:name]; 
    [NSKeyedArchiver archiveRootObject:object toFile:appFile]; 
} 

-(NSObject *)loadFromFile:(NSString *)name { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:name]; 

    if([[NSFileManager defaultManager] fileExistsAtPath:appFile]) 
     return [NSKeyedUnarchiver unarchiveObjectWithFile:appFile]; 
    else{ 
     NSLog(@"No File: %@", name) ; 
     return nil ; 
    } 

}