繁体   English   中英

iPhone-将NSMutableDictionary写入文件

[英]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)所指出的,当您没有文件时,您的代码将跳过对favoriteJokesDictionaryfavoriteJokes的初始化。 当您稍后尝试写出对象时, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM