【问题标题】:Should I use NSUserDefaults or a plist to store data?我应该使用 NSUserDefaults 还是 plist 来存储数据?
【发布时间】:2011-10-26 21:29:44
【问题描述】:

我将存储一些字符串(可能是 10-20)。我不确定是否应该使用 NSUserDefaults 来保存它们,或者将它们写到 plist 中。什么被认为是最佳实践? NSUserDefaults 似乎代码行数更少,因此实现起来更快。

我想补充一点,这些字符串值将由用户添加/删除。

【问题讨论】:

    标签: iphone objective-c cocoa-touch plist nsuserdefaults


    【解决方案1】:

    像这样持久化数据的推荐方法是使用 Core Data。虽然 NSUserDefaults 可用于存储或多或少的任何内容,但它只应用于存储首选项。

    【讨论】:

    • 为什么 Core Data 比 plist 更适合少数字符串?
    • 因为框架会处理所有细节,例如文件处理、同步和错误处理。
    • @MarcusKarlsson NSUserDefaults 也将为 OP 提供这种处理。在我看来,OP 列出的少量字符串更符合用户偏好,尽管更多信息将有助于在此处提供指导。
    • 如果我想存储 cookie 并且其中大约有 50 个怎么办。在这种情况下,我应该使用核心数据、nsuserdefaults 还是 plist?
    【解决方案2】:

    这取决于您要存储什么以及为什么。 NSUserDefaults 用于存储用户偏好。您可以尝试将其用于其他用途,但您可能不应该这样做。

    否则,如果您的需求很简单,则 plist 文件非常简单。您还可以使用核心数据或提出自己的文件格式。一般来说,我将 plist 用于简单的任务,然后转移到核心数据来处理更复杂的任务。

    【讨论】:

      【解决方案3】:

      如果您要存储 10 到 20 个字符串并且寻找的代码行数不多,那么核心数据的开销肯定会太大。我建议使用 plist。代码不多:

      NSURL *plistURL = [[NSBundle mainBundle] URLForResource:@"MyStrings" withExtension:@"plist"];
      NSArray *stringArray = [NSArray arrayWithContentsOfURL:plistURL];
      

      【讨论】:

        【解决方案4】:

        NSUserDefaults 会将用户首选项存储到 Library/Preferences 文件夹中的文件中。从理论上讲,它仅用于存储一些应用程序/用户属性。

        Plist 文件对于管理单个文件很有用。如果你需要管理更多,你应该使用 Coredata。 plist 文件的大小没有限制。否则你必须小心 plist 文件,因为当你需要保存或读取它时,文件的全部内容将被加载到内存中。

        【讨论】:

          【解决方案5】:

          我假设是一个数组,但它也适用于字典。

          Userdefaults、Core Data 和 Plists 都可以读/写,但是如果你使用 plist,你需要注意你把它放在什么目录下。请参阅下面的 plist 部分。

          Core Data 我认为这太过分了,它只是字符串。 当您想要持久化更复杂的对象时应该使用它。

          NSUserDefaults

          虽然它应该只存储用户设置,但它非常快速且易于操作。 要将它们写入用户默认值:

          NSArray *stringsArray = [[NSArray alloc] arrayWithObjects: string1, string2, string3, nil];
          [[NSUserDefaults standardUserDefaults] setObject:stringsArray forKey:@"MyStrings"];
          [[NSUserDefaults standardUserDefaults] synchronize];
          

          从用户默认值中读取:

          NSArray *stringsArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"MyStrings"];
          

          列表

          如果要修改您的字符串,您将需要写入和读取 plist,但您不能写入应用的资源。

          1. 要有一个读/写plist首先找到文档目录

            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
            
          2. 创建数组(我假设字符串是 string1,...)

            NSArray *stringsArray = [[NSArray alloc] arrayWithObjects: string1, string2, string3, nil];
            
          3. 写入文件

            [stringsArray writeToFile:stringsPlistPath atomically:YES];
            

          阅读 plist:

          1. 找到文档目录

            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
            
          2. 阅读:

            NSArray *stringsArray = [NSArray arrayWithContentsOfFile:stringsPlistPath];
            

          【讨论】:

          • 我为最近使用的 URL 列表实现了 PList 解决方案。 PList 似乎是解决我的问题的正确方法。但我不得不说,在 Android 上做了同样的事情之后,就学习曲线和整体努力而言,这令人惊讶地更多。所以我不得不评论并说非常感谢上面的示例代码......
          • 问题...当您说“您无法写入您的应用程序资源”时,您的意思是我们无法写入我们在 xcode 中创建和填充的 plist 吗?
          • 您只能在应用的 Documents 目录中写入。因此,您可以在运行时将该 plist 从 Resources 目录复制到 Documents 目录,然后对其进行编辑。
          • 我想添加要在我的应用程序中使用的 URL 列表。 plist 是一个安全的选择吗?我不希望我的 UR 被扼杀
          【解决方案6】:

          如果字符串不仅仅是可以进入 NSUserDefaults 的用户设置,则使用 plist 是存储字符串的好选择。如前所述,使用 plist 时,您必须将 plist 存储在 Documents 目录中才能写入,因为您无法写入自己应用程序的资源。当我第一次了解到这一点时,我不清楚您自己的应用程序的 Bundle 目录与 Documents 目录的位置,所以我想我会在这里发布示例代码,首先复制一个名为“Strings.plist”的 plist(即您已经在自己的应用程序的 Bundle 目录中)复制到 Documents 目录,然后对其进行写入和读取。

          // Make a path to the plist in the Documents directory
          NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
          NSString *stringsPlistPathIndDoc = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
          
          // Make a path to the plist in your app's Bundle directory
          NSString *stringsPlistPathInBundle = [[NSBundle mainBundle] pathForResource:@"Strings" ofType:@".plist"];
          
          NSFileManager *fileManager = [NSFileManager defaultManager];
          
          // Check first that you haven't already copied this plist to the Documents directory
          if (![fileManager fileExistsAtPath:stringsPlistPathIndDoc])
          {
              NSError *error;
          
              // Copy the plist from the Bundle directory to the Documents directory 
              [fileManager copyItemAtPath:stringsPlistPathInBundle toPath:stringsPlistPathIndDoc error:&error];
          }
          
          // Write your array out to the plist in the Documents directory
          NSMutableArray *stringsArray = [[NSMutableArray alloc] initWithObjects:@"string1", @"string2", @"string3", nil]; 
          [stringsArray writeToFile:stringsPlistPathIndDoc atomically:YES];
          
          // Later if you want to read it:
          stringsArray = [[NSMutableArray alloc] initWithContentsOfFile:stringsPlistPathIndDoc];
          

          【讨论】:

            【解决方案7】:

            iOS 最终将所有 NSUserDefaults 数据存储到 plist 文件中。因此,如果这是您关心的问题,它不会影响性能。我个人更喜欢使用NSUserDefaults 处理小数据,使用 plist 处理相对较大的数据集。

            注意:切勿将任何敏感信息存储在 NSUserDefaults 中,因为任何人都可以看到这些数据。

            【讨论】:

              【解决方案8】:

              使用 .plist

              1. 使用 Xcode 创建 plist

              向 plist 写入值

              NSURL *plistURL = [[NSBundle mainBundle] URLForResource:@"settings" withExtension:@"plist"];
              
               NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfURL:plistURL];
               [dict setValue:@"value" forKey:@"key"];
               [dict writeToURL:plistURL atomically:YES];
              

              从 plist 中读取一个值

              NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfURL:plistURL];
              NSString *myValue = [dict valueForKey:@"key"];
              

              【讨论】:

                【解决方案9】:

                NSUSerDefaults确实实现起来很快,但是主要是随着你的应用程序的增长,你想要存储的越来越多,我直接去找了plist文件。

                大多数情况下,人们想要存储一些东西的列表,所以这里是我关于如何使用 NSDictionary 做到这一点的分享。这不需要你先创建一个plist文件,它会在第一次创建保存一些东西

                xcode 7 测试版,Swift 2.0

                保存

                func SaveItemFavorites(items : Array<ItemFavorite>) -> Bool
                {
                    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
                    let docuDir = paths.firstObject as! String
                    let path = docuDir.stringByAppendingPathComponent(ItemFavoritesFilePath)
                    let filemanager = NSFileManager.defaultManager()
                
                    let array = NSMutableArray()        
                    
                    for var i = 0 ; i < items.count ; i++
                    {
                        let dict = NSMutableDictionary()
                        let ItemCode = items[i].ItemCode as NSString
                        
                        dict.setObject(ItemCode, forKey: "ItemCode")
                        //add any aditional..
                        array[i] = dict
                    }
                    
                    let favoritesDictionary = NSDictionary(object: array, forKey: "favorites")
                    //check if file exists
                    if(!filemanager.fileExistsAtPath(path))
                    {
                        let created = filemanager.createFileAtPath(path, contents: nil, attributes: nil)
                         if(created)
                         {
                             let succeeded = favoritesDictionary.writeToFile(path, atomically: true)
                             return succeeded
                         }
                         return false
                    }
                    else
                    {
                        let succeeded = notificationDictionary.writeToFile(path, atomically: true)
                        return succeeded
                    }
                }
                

                来自文档的小注释:

                NSDictionary.writeToFile(path:atomically:)

                此方法在写出文件之前递归地验证所有包含的对象都是属性列表对象(NSDataNSDateNSNumberNSStringNSArrayNSDictionary 的实例),如果所有对象都不是属性列表对象,则返回 NO,因为结果文件不是有效的属性列表。

                所以你在dict.SetObject() 设置的任何东西都应该是上述类型之一。

                加载中

                private let ItemFavoritesFilePath = "ItemFavorites.plist"
                
                func LoadItemFavorites() -> Array<ItemFavorite>
                {
                    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
                    let docuDir = paths.firstObject as! String
                    let path = docuDir.stringByAppendingPathComponent(ItemFavoritesFilePath)
                    let dict = NSDictionary(contentsOfFile: path)
                    let dictitems : AnyObject? = dict?.objectForKey("favorites")
                    
                    var favoriteItemsList = Array<ItemFavorite>()
                    
                    if let arrayitems = dictitems as? NSArray
                    {
                        for var i = 0;i<arrayitems.count;i++
                        {
                            if let itemDict = arrayitems[i] as? NSDictionary
                            {
                                let ItemCode = itemDict.objectForKey("ItemCode") as? String
                                //get any additional
                                
                                let ItemFavorite = ItemFavorite(item: ItemCode)
                                favoriteItemsList.append(ItemFavorite)
                            }
                        }
                    }
                    
                    return favoriteItemsList
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-01-31
                  • 2010-12-25
                  • 2016-01-02
                  • 2011-06-25
                  • 1970-01-01
                  相关资源
                  最近更新 更多