2014-09-02 101 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 ; 
    } 

}