Iphone 读取/写入应用程序附带的plist文件

Iphone 读取/写入应用程序附带的plist文件,iphone,plist,nsdictionary,Iphone,Plist,Nsdictionary,我正在为我的应用程序构建一个附加组件,用户可以在其中搜索预先填充了.plist文件数据的列表中的项目。这是一本词典。如果用户搜索的术语不存在,用户可以点击+按钮并添加它,以便下次出现 首先,我认为它和使用NSUserDefaults一样简单,但是出现了一些问题 要包含该列表,我必须将其放在bundle中,但如果它存在,我就不能向其中添加新的键/值对。我只能处理位于Documents文件夹中的文件 所以我想我必须捆绑plist,然后在第一次运行时,我将把它移动到documents文件夹并在那里访问

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

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

要包含该列表,我必须将其放在bundle中,但如果它存在,我就不能向其中添加新的键/值对。我只能处理位于Documents文件夹中的文件

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

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

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

感谢您的帮助:)

编辑:******实际方法,如Squad和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];

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

我最终就是这样做的,将绑定的文件复制到文档中,以便能够修改它

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


唯一的问题是,如果希望升级plist,则必须在应用程序中处理该问题。如果必须这样做,我建议您使用NSUserDefault检查之前是否存在该应用程序的早期版本…

我对我的sqlite数据库有相同的想法

我最终就是这样做的,将绑定的文件复制到文档中,以便能够修改它

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


唯一的问题是,如果希望升级plist,则必须在应用程序中处理该问题。如果必须这样做,我建议您使用NSUserDefault检查应用程序的早期版本是否存在…

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


当用户删除应用程序时,文档目录的内容将被删除


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

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


当用户删除应用程序时,文档目录的内容将被删除


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

谢谢Tom:)我同意您的建议,测试文件是否在文档文件夹中找到。这是一个很少被调用的操作,只有在边缘情况下,用户去做一些正常使用之外的事情。因此,测试文件是否存在所带来的小开销是由灵活性决定的。谢谢Tom:)我同意你关于测试文件是否在documents文件夹中找到的建议。这是一个很少被调用的操作,只有在边缘情况下,用户去做一些正常使用之外的事情。因此,测试文件是否存在所带来的小开销是由灵活性所决定的。感谢squad:)我将其作为代码的大致部分放在一起,并将其放在我的答案中。我工作很好。我想我永远不应该覆盖plist,因为这会导致我不得不将用户添加的内容与我添加的内容合并,我想是同步的。一个边缘案例有很多工作要做。也许我将来会做一些时间戳。试着尽可能少地更新文档中的文件,这样做真的很痛苦,相信我!我因此得到了不好的更新,当然也带来了不好的评论。。。现在,为了测试从一个版本到另一个版本的更新,我保留了我发布的每个版本的精确副本,我建议你也这样做,否则你会后悔:-)如果我知道我将来会在plist中放入什么,我会容易得多:)谢谢TheSquad:)我将代码的大致部分放在一起,并将其放在我的答案中。我工作很好。我想我永远不应该覆盖plist,因为这会导致我不得不将用户添加的内容与我添加的内容合并,我想是同步的。一个边缘案例有很多工作要做。也许我将来会做一些时间戳。试着尽可能少地更新文档中的文件,这样做真的很痛苦,相信我!我因此得到了不好的更新,当然也带来了不好的评论。。。现在,为了测试从一个版本到另一个版本的更新,我保留了我发布的每个版本的精确副本,我建议您也这样做,否则您会后悔:-)如果我知道我将来会在plist中添加什么,我会更容易:)