[英]iPhone - Writing NSMutableDictionary to file
将可变字典写入文件时遇到麻烦。 这是我正在编写的代码。 我正在读取文件,如下所示:(第一次运行应用程序时,它没有任何数据)
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;
}
我不知道为什么它不把字典拧到文件上。 谁能指出我的错误?
当将Cocoa API写出到文件中时,它在字典中可以合法地使用哪种值非常具体。 已知会导致问题的一个特殊限制,并且在官方API文档中没有进行全面讨论,该限制是词典中的所有键都必须为NSString类型(并且您的值必须为NSData,NSDate,NSNumber,NSString之一) ,NSArray或NSDictionary),即使字典本身支持任何对象类型的键和值。
此限制的原因与以下事实有关:默认情况下,该词典存储为XML文档(在Apple语中为“属性列表”)。 因此,我建议您验证您的词典是否符合保存到文件的要求,如果不符合,请对其进行重组。
或者,如果重组字典不可行,则可能需要查看NSKeyedArchiver类。
当没有保存文件进行初始化时,您似乎favoriteJokesDictionary
喜欢的favoriteJokesDictionary
根本不存在。 因此,尝试从addJokeToFavorite:
中不存在的字典中创建保存文件的尝试也没有任何作用。 当没有保存文件开始时,您需要创建一个空字典。
Ulrich发布正确答案时,我只是在输入此信息。 我将在此处添加其余内容以进一步澄清。
正如乌尔里希(Ulrich)所指出的,当您没有文件时,您的代码将跳过对favoriteJokesDictionary
和favoriteJokes
的初始化。 当您稍后尝试写出对象时, favoriteJokesDictionary
为nil,因此该方法不执行任何操作。
如果文件尚不存在,则可以仅创建一个空的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"];
}
就是说,我认为您可能可以稍微简化一下数据模型(除非发生了更多未显示的事件)。 如果您因为要存储的不仅仅是笑话而需要词典,那么您拥有的就很好。 但是,我不会保留jokes数组,因为如果您稍后在数组中为JokesArrayKey设置一个新对象,则您最喜欢的jokes ivar仍将指向旧数组。
我只是在需要时才从字典中获取对象:
NSMutableArray *jokes = [favoriteJokesDictionary objectForKey:@"JokesArrayKey"];
更好的是,如果您正在使用jokes数组进行大量操作,只需将其拉出到其自己的文件中即可。 您可以像使用NSDictionary一样将NSArray写为plist。 如果仅使用NSDictionary作为外壳程序来写出.plist,则可以完全跳过它。
另一件事:假设favSaveFilePath
属性标记为“保留”,则在第一部分中有少量内存泄漏。 您正在使用[[NSString alloc] initWithString:...]
创建一个新的保留字符串,然后通过将其分配给您的属性来再次保留它。 您可能只想要:
self.favSaveFilePath = [documentsDirectory stringByAppendingPathComponent:@"Favorites.plist"];
关于aroth给出的答案,词典中的非ns对象可能比您意识到的要微妙得多。 EG:我有一个NSDictionary
对象的NSArray
,我将其变成NSObject
子类的项,并将它们添加到NSMutableDictionary
。 即使子类仅包含基于NS的对象,字符串等; NSMutableDictionary
本身不会保存。
解决的方法是保存NSDictionary
项的NSArray
,并在加载文件后将它们变成我的自定义子类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.