在NSUserDefaults中存储值是否有限制?


73

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

提前致谢。


NSUserDefaults用于相对少量的数据,非常频繁地查询,并偶尔进行修改。与更适合那些用途的解决方案相比,以其他方式使用它可能会比较慢或占用更多内存。当前,除了tvOS上,本地用户默认值没有限制。我在UserDefaults上通过“ cmd单击”找到了此信息,该信息将您带到其源文件。我阅读了该文档,以查找此信息,但是找不到该信息。
鲍比(Bobby)

1
我不确定,但是您可以看到此链接
TheTiger

Answers:


55

只要iPhone / iPad上有足够的空间,您就可以存储NSUserDefault值。所有这些值都存储在.plist文件中,并且此文件非常小,大多数情况下不到1 kb(除非您存储大量数据)。


添加大文件/数据后,对设备性能有影响吗?
iDeveloper

可能是正确的,但请参阅此链接。什么是正确的?
TheTiger

46

还有你可以存储什么类型的限制:它们必须属性列表对象,即NSStringNSNumberNSDataNSArray,和NSDictionary。此外,你可能只存储NSArrayNSDictionary当值也是属性列表对象; 同样,NSDictionary必须的所有键都必须是字符串。

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

至于大小限制,没有任何记录,但是请注意,所有数据都将存储为属性列表文件。整个文件作为一个整体被读取和写入,因此,如果您用于NSUserDefaults存储仅部分更改的大量数据,则将浪费大量时间进行不必要的I / O。


5
关于单个文件这一点很关键。非常好的信息,谢谢。
MobileVet 2014年

13

每个人都回答了“有极限吗?”这个直接问题。但是,我发现此线程确实希望了解“多少就是太多在UserDefaults中存储存储空间?”

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

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


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


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

重要提示:

上面的内容缓解了我对我越来越多的默认值(现在大约为20-25)会引起问题的担忧。我已经使用CoreData了,所以我正在考虑使用哪个,因为我允许的用户首选项/自定义数目越来越长。因此,我将保留用户默认设置。

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


11

来自iOS SDK代码以及相关的Apple官方文档。

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

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

尽可能有可用的存储空间中的设备,你几乎可以存储数据。的-对存储在一个XML结构的文件(plist中其被存储在一个)应用程序包iOS NSUserDefaults

用户默认系统和键值存储库都旨在将简单的数据类型(字符串数字日期布尔值, URL数据对象等)存储在属性列表中。使用属性列表还意味着您可以使用数组和字典类型来组织您的首选项数据。通过将其他NSData对象首先编码为对象,也可以将它们存储在属性列表中。


5

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

真正的问题应该是您如何经常编写新的/更改的值...这与写入将导致的电池消耗有关。

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

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

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

最小化数据写入。仅当文件的内容已更改时才写入文件,并尽可能将更改汇总到单个写入中。如果仅更改了几个字节,请避免写出整个文件。如果您经常更改大文件的一小部分,请考虑使用数据库来存储数据。

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

编辑:(2019年7月):我刚刚发现了杰弗里·富尔顿的这篇很好的博客文章。

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

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



4

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

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

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


我也有这个问题!您找到原因/解决方案了吗?
SAHM

@SAHM不确定原因。由于我只是将单个图像保存为用户首选项,因此我最终将数据写入了documents文件夹,而不是使用用户默认值。
道格

出于好奇,@ Doug,保存后是否使用了“同步”?
SAHM,

如果您想聊天,我对此有一些想法。
SAHM

@SAHM不,我没打电话synchronize。如文档中所述,“此方法是不必要的,不应使用。”
道格


0

无论驱动器上允许的最大文件大小如何。您可以使用这段代码进行检查!

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);
}

5
FYIint值没有那么高,因此循环中最终会出现溢出(假设经过约2.15B次迭代)。但在此之前,您最终会溢出sizeOfFile
Stonz2 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.