2009-01-23 40 views
144

我想在NSUserDefaults中保存一個NSMutableDictionary對象。 NSMutableDictionary中的密鑰類型爲NSString,值類型爲NSArray,其中包含實現NSCoding的對象列表。根據文件,NSStringNSArray均符合NSCoding爲什麼NSUserDefaults無法在iPhone SDK中保存NSMutableDictionary?

我收到此錯誤:

[NSUserDefaults setObject: forKey:]: Attempt to insert non-property value.... of class NSCFDictionary.

這個任何解決方案?

回答

229

我發現一個替代方案,在保存之前,我使用NSKeyedArchiver編碼根對象(NSArray對象),以NSData結尾。然後使用UserDefaults保存NSData

當我需要數據時,我讀出NSData,並使用NSKeyedUnarchiverNSData轉換回對象。

這是一個有點麻煩,因爲我需要每次轉換/從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; 
} 

任何人都有更好的解決方案嗎?

謝謝大家。

14

是字典中的所有密鑰NSString s?我認爲他們必須爲了將字典保存到物業清單。

+1

鍵是NSString。但值是NSArray,其元素是一個實現NSCoding的定製類。看起來解決方案不工作,因爲UserDefaults只支持6種類型,不考慮NSCoding。 – BlueDolphin 2009-01-23 21:11:10

105

如果要以用戶默認值保存對象,則所有對象以遞歸方式遞減,必須是屬性列表對象。符合NSCoding並不意味着什麼 - NSUserDefaults不會自動將它們編碼爲NSData,您必須自己做。如果你的「實現NSCoding的對象列表」表示不是屬性列表對象的對象,那麼在保存爲用戶默認值之前,你必須對它們做些什麼。

供參考的財產清單類NSDictionaryNSArrayNSStringNSDateNSDataNSNumber。你可以寫出可變的子類(如NSMutableDictionary)給用戶的喜好,但你讀出的對象將永遠是不可變的。

+60

我還應該提到,如果鍵是NSStrings,NSDictionary只是一個屬性列表對象。一般來說,您可以使用其他對象作爲字典鍵,但在需要屬性列表的情況下,鍵必須是字符串。 – 2009-01-23 04:45:32

+0

我遇到了同樣的問題,當我想將NSURL作爲對象存儲在NSDictionary中並將其存儲在NSUserDefaults中時。我不得不將它改成NSString,而不是它的工作。 – NicTesla 2011-10-31 09:46:26

+1

太棒了!在我的情況下,我試圖使用NSNumber作爲用戶默認的NSDictionary的關鍵。我必須將其更改爲NSString。 – Joey 2012-05-25 01:40:09

0

沒有更好的解決方案。另一個選擇是將編碼的對象保存到磁盤 - 但這是做同樣的事情。他們最終都會得到NSData,當你想要它時,它會被解碼。

5

您是否考慮過在實施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的兩個方法。

我希望這有助於!

7

簡單的答案:

NSDictionary只是的plist對象,如果鍵NSString的。 因此,將「鑰匙」作爲NSStringstringWithFormat


解決方案:

NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]]; 

優點:

  1. 這將增加字串值
  2. 當您的變量值爲NULL時,它將添加空值
相關問題