2011-03-19 52 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项,并在加载文件后将它们变成我的自定义子类。