2011-03-19 66 views
0

我在將可變字典寫入文件時遇到問題。這是我寫的代碼。 我讀文件象下面這樣:(第一次,當應用程序是跑步,它不會有任何數據)iPhone - 將NSMutableDictionary寫入文件

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString* documentsDirectory = [paths objectAtIndex:0]; 
self.favSaveFilePath = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:@"Favorites.plist"]]; 
if([fm fileExistsAtPath:favSaveFilePath]) 
{ 
    favoriteJokesDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:self.favSaveFilePath]; 
    favoriteJokes = [[NSMutableArray alloc] initWithArray:[self.favoriteJokesDictionary objectForKey:@"FavoriteJokes"]]; 
    return; 
} 

我加入新的字典,數組如下:

-(BOOL)addJokeToFavorite:(NSDictionary*)joke 
{ 
    BOOL success = NO; 
    [self.favoriteJokes addObject:joke]; 
    success = [self.favoriteJokesDictionary writeToFile:self.favSaveFilePath atomically:YES]; 
    return success; 
} 

我不知道爲什麼它不要把字典存檔。任何人都可以指出我正在做的錯誤嗎?

回答

9

Cocoa API非常具體,它可以在字典寫入文件時合法地在字典中使用哪種類型的值。已知會導致問題並且在官方API文檔中未詳細討論的一個特定限制是,字典中的所有鍵必須是NSString類型的鍵(並且您的值必須是NSData,NSDate,NSNumber,NSString之一,NSArray或NSDictionary),即使字典本身支持任何對象類型的鍵和值。

此限制的原因與默認情況下字典以XML文檔(或Apple發言中的「屬性列表」)存儲的事實有關。因此,我建議您驗證您的字典是否符合要保存到文件中的要求,如果不符合,請重新構建它。

或者,如果重組字典不可行,那麼您可能需要查看NSKeyedArchiver類。

1

看起來像你的favoriteJokesDictionary根本不存在,當沒有保存文件來初始化它。因此,從addJokeToFavorite:中不存在的字典中創建保存文件的嘗試也不會執行任何操作。當沒有保存文件開始時,您需要創建一個空字典。

1

我只是在Ulrich發佈正確答案時輸入了這個信息。我會在這裏補充說明。

正如Ulrich指出的那樣,當您沒有文件時,您的代碼會跳過favoriteJokesDictionaryfavoriteJokes的初始化。當您稍後嘗試寫出對象時,favoriteJokesDictionary爲零,因此該方法不起任何作用。

如果文件不存在,您可以創建一個空的NSMutableDictionary,並且由於您將字典的一部分保留在單獨的ivar中,因此應該同時創建它。像這樣的東西會工作:

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString* documentsDirectory = [paths objectAtIndex:0]; 
self.favSaveFilePath = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:@"Favorites.plist"]]; 
if([fm fileExistsAtPath:favSaveFilePath]) 
{ 
    favoriteJokesDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:self.favSaveFilePath]; 
    favoriteJokes = [[NSMutableArray alloc] initWithArray:[self.favoriteJokesDictionary objectForKey:@"FavoriteJokes"]]; 
} else { 
    favoriteJokesDictionary = [[NSMutableDictionary alloc] init]; 
    favoriteJokes = [[NSMutableArray alloc] init]; 
    [favoriteJokesDictionary setObject:favoriteJokes forKey:@"JokesArrayKey"]; 
} 

這麼說,我想你大概可以簡化您的數據模型有一個位(除非有更多的事情,你不顯示)。如果你需要一本詞典,因爲你不僅僅存儲笑話,那麼你擁有的就是好的。但是,我不會保留笑話數組,因爲如果稍後在數組中爲您的JokesArrayKey設置了新對象,那麼您最喜歡的笑話ivar仍然會指向舊數組。

我只想抓住從字典中的對象,而不是隻要你需要它:

NSMutableArray *jokes = [favoriteJokesDictionary objectForKey:@"JokesArrayKey"]; 

更妙的是,如果你是談笑風聲陣列工作相當多,剛拉出來到自己的文件。你可以像使用NSDictionary一樣將一個NSArray寫成plist。如果您只是使用NSDictionary作爲shell來寫出.plist,則可以完全跳過它。

另一件事:假設favSaveFilePath屬性標記爲「保留」,則第一部分中的內存泄漏很小。您正在創建一個新的保留字符串[[NSString alloc] initWithString:...],然後通過將其分配給您的財產再保留它。你可能只是想:

self.favSaveFilePath = [documentsDirectory stringByAppendingPathComponent:@"Favorites.plist"]; 
0

參考答案,你的字典中的非ns對象可能比你意識到的更微妙。 EG:我有一個NSArrayNSDictionary對象,我正在變成NSObject子類項目,並將它們添加到NSMutableDictionary。 儘管子類只包含基於NS的對象,字符串等; NSMutableDictionary本身不會保存。

解決的辦法是保存NSArrayNSDictionary項,並在加載文件後將它們變成我的自定義子類。