【问题标题】:Read/Write to a plist file that comes bundled with the app读取/写入与应用程序捆绑在一起的 plist 文件
【发布时间】:2010-09-26 12:46:05
【问题描述】:

我正在为我的应用程序构建一个插件,用户可以在其中搜索列表中的项目,该列表中预先填充了来自 .plist 文件的数据。它是一个 NSDictionary。如果用户搜索的词不存在,用户可以点击 + 按钮并添加它,以便下次出现。

首先我认为它就像使用 NSUserDefaults 一样简单,但出现了一些问题。

要包含列表,我必须将其放入捆绑包中,但如果存在,我无法向其中添加新的键/值对。我只能对位于 Documents 文件夹中的文件执行此操作。

所以我想我必须捆绑 plist,然后在第一次运行时将它移动到文档文件夹并在那里访问它。

当我需要更新应用程序时,这会引发问题,我猜它会覆盖用户输入的值。

是否有一种安全、易于理解、正确的方法来实现我描述的功能?

感谢您提供的任何帮助:)

编辑:**** TheSquad 和 TomH 建议的实际方法*****

+ (NSMutableDictionary*) genericProducts {

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [documentPaths objectAtIndex:0];
    NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:@"GenericProducts.plist"];

    NSString *bundlePath = [[NSBundle mainBundle] bundlePath];  
    NSString *bundlePlistPath = [bundlePath stringByAppendingPathComponent:@"GenericProducts.plist"];


    if([fileManager fileExistsAtPath:documentPlistPath]){

        NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
        return documentDict;

    } else {

        NSError *error;
        BOOL success = [fileManager copyItemAtPath:bundlePlistPath toPath:documentPlistPath error:&error];

    if (success) {
        NSMutableDictionary *newlySavedDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
        return newlySavedDict;
    }

    return nil;
}

}

以及将新产品添加到列表中:

+ (void) addItemToGenericProducts:(NSString*) newProduct {

    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [documentPaths objectAtIndex:0];
    NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:@"GenericProducts.plist"];
    NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
    [documentDict setObject:newProduct forKey:[MD5Checksum cheksum:newProduct]];

    [documentDict writeToFile:documentPlistPath atomically:YES];

}

【问题讨论】:

    标签: iphone plist nsdictionary


    【解决方案1】:

    我对我的 sqlite 数据库也有同样的想法......

    我最终就是这样做的,将捆绑的文件复制到文档中以便能够对其进行修改。

    我所做的是在每次启动时检查文件是否存在,如果不存在,则复制它。 如果您更新您的应用程序,不会触摸文档文件夹,这意味着从之前版本复制的文件仍然存在。

    唯一的问题是,如果你想升级你的 plist,你必须在你的应用程序中处理它。如果你必须这样做,我建议你使用 NSUserDefault 来检查之前是否存在应用程序的早期版本......

    【讨论】:

    • 感谢 TheSquad :) 我将代码粗略地整理在一起,并将其放在我的答案中。我工作得很好。我想我永远不应该覆盖 plist,因为这将导致我不得不将用户添加的内容与我添加的内容合并,我猜是同步的。边缘案例需要做很多工作。也许我将来会做一些时间戳。
    • 尝试尽可能少地更新文档中的文件,这样做真的很痛苦,相信我!因此,我得到了糟糕的更新,当然还有随之而来的糟糕评论......现在我保留了我发布的每个版本的精确副本,以便测试从一个版本到另一个版本的更新,我建议你也这样做,否则你会后悔的:-)
    • 如果我知道将来我会在 plist 中添加什么,我会轻松很多:)
    【解决方案2】:

    更新应用程序时不会更改文档目录的内容。

    用户删除应用时,文档目录的内容也会被删除。

    当应用程序第一次运行时,将一个标志写入 NSUserDefaults。在应用程序的后续运行中,检查标志是否存在。 (或者,您可以只检查文档目录中是否存在 plist)

    【讨论】:

    • 谢谢汤姆:)我同意了您关于测试文件是否在文档文件夹中的建议。这是一个很少被调用的动作,仅在用户去做正常使用之外的事情的边缘情况下。因此,测试文件是否存在所带来的少量开销被灵活性所抵消。
    猜你喜欢
    • 2011-11-02
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    相关资源
    最近更新 更多