【问题标题】:Is there any limit in storing values in NSUserDefaults?在 NSUserDefaults 中存储值是否有任何限制?
【发布时间】:2011-11-22 12:47:15
【问题描述】:

我是 iPhone 开发的新手,objective C。 我使用NSUserDefaults 在我的应用程序中存储了一些值。 但我不知道在NSUserDefaults 中存储值是否有任何限制。 谁能帮我知道这一点。

提前致谢。

【问题讨论】:

  • NSUserDefaults 适用于相对少量的数据,查询非常频繁,偶尔修改。与更适合这些用途的解决方案相比,以其他方式使用它可能会很慢或使用更多内存。目前对本地用户默认设置没有限制,除了 tvOS。我通过 UserDefaults 上的“cmd click”找到了这些信息,它会将您带到他们的源文件。我阅读了寻找此信息的文档,但在那里找不到。
  • 我不确定,但你可以看到这个link

标签: iphone objective-c ios xcode nsuserdefaults


【解决方案1】:

只要 iPhone/iPad 上有足够的空间,您就可以存储 NSUserDefault 值。所有这些值都存储在一个 .plist 文件中,而且这个文件非常小,大部分时间都在 1 kb 以下(除非您存储大量数据)。

【讨论】:

  • 添加大文件/数据后对设备性能有影响吗?
  • 可能是真的,但请参阅link。什么是正确的?
【解决方案2】:

您可以存储的类型有限制:它们必须都是属性列表对象,即NSStringNSNumberNSDataNSArrayNSDictionary。此外,如果值也是属性列表对象,则只能存储 NSArrayNSDictionary;另外,NSDictionary 的所有键都必须是字符串。

请注意,像UIColor 这样的对象不在上面的列表中。因此,如果您想在默认数据库中存储颜色,您需要先将其转换为字符串或数据对象,然后在读取默认值时将其转换回来。

就大小限制而言,没有记录,但请注意,所有数据都将存储为属性列表文件。整个文件是整体读入写出的,所以如果你使用NSUserDefaults来存储大量只是局部变化的数据,你会浪费很多时间做不必要的I/O。

【讨论】:

  • 这是一个单独的文件,这一点非常关键。非常好的信息,谢谢。
【解决方案3】:

每个人都回答了“有限制吗?”这个直接问题。但是,我发现这个帖子真的很想了解“多少是太多无法存储在 UserDefaults 中?”

如果您正在寻找答案,这里有一个有用的thread。我发现有帮助的回复是转到您的项目文件并查看 plist 文件大小:

5 个对象几乎没有。你会没事的!


在我的机器上,我的用户默认值中有大约 28 兆的数据。这根本不会造成任何问题。


根据数组的一般编程经验,我猜当你达到 1000 个时,性能会开始迅速下降,具体取决于元素大小。因此,在程序中存储几百个元素不会有问题。这就是说,如果我是你,我可能会尽快开始使用 sqlite3 数据库或 coredata。

重要提示:

以上内容减轻了我的担忧,即我越来越多的默认值(现在大约 20-25 个)会导致问题。我已经在使用 CoreData,所以我正在考虑使用哪个,因为我允许的用户偏好/自定义数量正在增长。所以,我将继续使用用户默认设置。

但是,正如其他答案所指出的那样,文件将作为一个整体进行读写。因此,阅读 20 个键/字符串字典和 5 个键/布尔字典只是为了检索一个字符串……并不完全理想。尽管如此,如果它不影响性能并且为您节省大量代码,为什么不呢?

【讨论】:

    【解决方案4】:

    来自 iOS SDK 代码和related Apple official document.

    extension UserDefaults {
    
    
        /*!
         NSUserDefaultsSizeLimitExceededNotification is posted on the main queue when more data is stored in user defaults than is allowed. Currently there is no limit for local user defaults except on tvOS, where a warning notification will be posted at 512kB, and the process terminated at 1MB. For ubiquitous defaults, the limit depends on the logged in iCloud user.
         */
        @available(iOS 9.3, *)
        public class let sizeLimitExceededNotification: NSNotification.Name
    
    
        // ....
     }   
    


    总结

    1. 目前本地用户默认设置没有限制
    2. tvOS 上,将以 512kB 的大小发布警告通知,进程以 1MB 的大小终止。
    3. 对于普遍存在的默认设置,限制取决于登录的 iCloud 用户。

    【讨论】:

      【解决方案5】:

      从 iPadOS 13.1 beta 3 开始,我现在在尝试存储更大的对象(图像)时看到以下消息。

      2019-09-14 11:01:29.634368+0100 MyApp[1686:147223] [用户默认值] CFPrefsPlistSource(域:com.example.MyApp,用户: kCFPreferencesCurrentUser,ByHost:否,容器:(空),内容 需要刷新:否):尝试将 >= 4194304 字节的数据存储在 此平台上的 CFPreferences/NSUserDefaults 无效。这是一个 MyApp 或其使用的库中的错误

      但是检索密钥似乎仍然有效。

      【讨论】:

      • 我也有这个问题!找到原因/解决办法了吗?
      • @SAHM 不确定原因。由于我只是将单个图像保存为用户首选项,因此我最终将数据写入文档文件夹而不是使用用户默认值。
      • 出于好奇,@Doug,您是否在保存后使用了“同步”?
      • 如果你想聊天,我有一些想法。
      • @SAHM 不,我没有打电话给synchronize。如文档中所述,“此方法是不必要的,不应使用。”
      【解决方案6】:

      正如许多人已经提到的:我不知道将数据存储在 .plist(例如 UserDefaults)中的任何 SIZE 限制(物理内存除外)。所以这不是多少钱的问题。

      真正的问题应该是您多久写入一次新的/更改的值...这与写入将导致的电池消耗有关。

      如果单个值更改,IOS 没有机会避免物理写入“磁盘”,只是为了保持数据完整性。关于 UserDefaults 这会导致整个文件重写到磁盘。

      这会启动“磁盘”并使其保持更长的供电时间,并防止 IOS 进入低功耗状态。

      摘自《iOS 应用能效指南》:

      尽量减少数据写入。仅在文件内容发生更改时才写入文件,并尽可能将更改聚合到单个写入中。 如果只更改了几个字节,请避免写出整个文件。如果您经常更改大文件的一小部分,请考虑改用数据库来存储数据。 p>

      读取没有问题,因为所有值都缓存在内存中。

      编辑:(2019 年 7 月):我刚刚发现 Jeffry Fulton 的这篇非常好的博文。

      https://jeffreyfulton.ca/blog/2018/02/userdefaults-limitations-and-alternatives

      他详细描述了用户默认值的不同方面,还写了一些性能测试。

      编码愉快!!!

      【讨论】:

        【解决方案7】:

        在 NSUserDefaults 中存储值没有限制..

        【讨论】:

        • 我收到此错误:尝试在此平台上的 CFPreferences/NSUserDefaults 中存储 >= 4194304 字节的数据无效。这是应用程序或其使用的库中的错误
        【解决方案8】:

        NSUserDefaults 中唯一的存储限制设备存储容量

        只要iOS 设备中有可用的存储空间,您实际上可以将数据存储在NSUserDefaults 中。 key-value 对存储在 xml 结构化文件 (.plist) 中,该文件存储在 App Bundle 中

        用户默认系统和键值存储都是为 存储简单的数据类型——字符串数字日期布尔值、 URLs、data 对象等等——在一个属性列表中。使用一个 属性列表还意味着您可以使用 数组和字典类型。也可以存储其他对象 在属性列表中,首先将它们编码为NSData 对象。

        【讨论】:

          【解决方案9】:

          据我所知,在 NSUserdefaults 中存储没有限制。

          【讨论】:

          • 我收到此错误:尝试在此平台上的 CFPreferences/NSUserDefaults 中存储 >= 4194304 字节的数据无效。这是 MyApp 或其使用的库中的错误
          【解决方案10】:

          无论驱动器上允许的最大文件大小是多少。你可以用这段代码来看看!

          NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
          NSString *myKey = @"key";
          int sizeOfFile = 1024; // Fill in proper file size here
          NSData myObject;
          NSString *someFilePath = @"PathToYourFileHere";
          
          for(int i = 1; i < 9999999999999999; i++)
          {
            myObject = [NSData dataWithContentsOfFile:someFilePath];
            [defaults setObject:myObject forKey:[NSString stringWithFormat:@"%@%i", myKey, i]];
            NSLog(@"Iteration: %i, TotalWritten: %i", i, i * sizeOfFile);
          }
          

          【讨论】:

          • 仅供参考 int 值不会那么高,因此您最终会在循环中出现溢出(假设您超过了 ~2.15B 迭代)。不过在那之前,你最终会溢出sizeOfFile
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-12-08
          • 1970-01-01
          • 2020-09-06
          • 1970-01-01
          • 1970-01-01
          • 2018-10-08
          • 1970-01-01
          相关资源
          最近更新 更多