2013-08-22 76 views
0

我試圖挽救一個NSDictionary NSUserDefaults的中,但我得到了以下錯誤: 嘗試插入非財產價值保存的NSDictionary NSUserDefaults的中

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 

if(defaults) { 
    [defaults setBool: YES forKey: @"disableGetStarted"]; 
    [defaults setObject: [json mutableCopy] forKey: @"user"]; 
    [defaults synchronize]; 

    NSLog(@"defaults %@", [defaults objectForKey: @"user"]); 
} 

凡JSON是一個NSDictionary。

我該怎麼辦?

+0

我不會建議保存一個龐大的'NSDictionary'作爲用戶的默認值。用戶默認不用於存儲大量的數據,因爲這有'Documents'文件夾。 – holex

+0

他並沒有說這本字典是大量的 –

+2

@AndreiStanescu,......而這正是我爲什麼假設字典是巨大的。 – holex

回答

2

json可能是一本字典,但字典中的所有內容都必須是合法的值才能存儲在用戶的默認值中。全部必須是以下實例:NSDataNSString,NSNumber,NSDate,NSArrayNSDictionary

+0

...和它們的可變版本(如果有的話)。 – holex

+1

@holex被子類包含在這樣的枚舉:) –

0

字典中的一個或多個對象不是NSString,NSArray,NSDictionary,NSDate或NSData,可能存在的唯一對象。此代碼可以幫助,它給你更多的細節,爲什麼你的字典裏是無效的:

- (BOOL)isValidPropertyList:(id)object { 

    // 
    // Check if `object` is a valid property list. 
    // 
    // # Return Value 
    // `YES` if the receiver is a valid property list, `NO` otherwise. 
    // 
    // # Discussion 
    // Intended to be called on NSArray and NSDictionary object to verify if the 
    // receiver is a valid property list. Will emit a description of any 
    // detected error. 
    // 
    NSData  *xmlData; 
    NSString *error; 

    xmlData=[NSPropertyListSerialization 
     dataFromPropertyList:object 
     format:NSPropertyListXMLFormat_v1_0 
     errorDescription:&error 
    ]; 
    if(xmlData) 
    { 
     return YES; 
    } 
    else 
    { 
     NSLog(@"Tested object is not a valid property list: %@",error); 
    } 

    return NO; 
} 
2

如果只存儲字典一樣的NSData,的NSString,NSNumber的,NSDate的,的NSArray,NSDictionary的或它們的組合內的標準對象你不必做任何特別的事情。但是,如果您有其中的自定義對象(即您創建的類)的實例,則首先需要將其轉換爲兼容類型(例如NSData)。爲此,可以使用下面的代碼做:

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

對於這種方法的工作,你定義來實現這2種方法中的自定義類,你要保存:

- (id)initWithCoder:(NSCoder*)coder 
- (void)encodeWithCoder:(NSCoder*)coder; 

爲了得到字典NSUserDefaults的距離(解碼)回你可以使用:

NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:@"user"]; 
NSDictionary* json = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

編輯

要檢查您的json對象包含任何[NSNull null]值,添加這段代碼你正在你的面前插入到NSUserDefaults

for (id val in [json allValues]) 
{ 
    if ([val isKindOfClass:[NSNull class]]) 
    { 
     NSLog(@"This bad! NSNull should not be in the dictionary"); 
     break; 
    } 
} 

如果你在控制檯的任何This is bad...的消息,那麼你有2種選擇。 1.使用我上面描述的存檔/解除存檔方法 2.如果這不會破壞您的代碼,請將字典中的NSNull對象替換爲其他值(例如空字符串)。

+0

已更新我的回答 –

+0

我在哪裏把initWithCoder和encodeWithCoder? nsdictionary中的項目是NSStrings。謝謝。 – user2491297

+0

如果項目是NSString那麼你不應該擔心它。只有存儲您創建的自定義類時,纔會使用這兩種方法。像其他人一樣,檢查json是否不包含任何[NSNull null]值。我將用一個示例代碼編輯我的帖子來完成此操作。 –

-1
NSDictionary *dict = [[NSDictionary alloc] init]; 

dict = json; 

[NSUserDefaults standardDefaults] setObject:dict forKey:@"user"]; 

NSUserDefaults不區分可變對象和不可變對象,所以當你得到它時它將是不可變的。所以,如果你讓偶然一個可變的字典 - >

[[NSUserDefaults standardDefaults] setObject:dict forKey:@"user"] mutableCopy]; 

字典json的所有對象都必須是實例:NSData的,的NSString,NSNumber的,NSDate的,NSArray的,或者NSDictionary的。