在 NSUserDefaults 中存储值有任何限制吗?

发布于 2024-12-05 18:17:39 字数 95 浏览 4 评论 0原文

我已使用 NSUserDefaults 在我的应用程序中存储一些值。在 NSUserDefaults 中存储值有任何限制吗?

I have used NSUserDefaults to store some values in my app. Is there any limit for storing values in NSUserDefaults?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

谁对谁错谁最难过 2024-12-12 18:17:39

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

As long as there's enough space on the iPhone/iPad, you can store NSUserDefault values. All those values is stored into a .plist file, and this file is very small, most of the time under 1 kb (unless you store a lot of data).

草莓味的萝莉 2024-12-12 18:17:39

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

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

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

There are limits on what types you may store: they must all be Property List objects, namely NSString, NSNumber, NSData, NSArray, and NSDictionary. Furthermore, you may only store NSArray and NSDictionary if the values are also property list objects; also, all the keys of the NSDictionary must be strings.

Note that an object like UIColor is not on the above list. So if you want to store a color in the defaults database, you'll need to convert it into a string or data object first, then convert it back when you read the defaults.

As far as size limits, there are none that are documented, but note that all data will be stored as a property list file. The entire file is read in and written out as a whole, so if you use NSUserDefaults to store a large amount of data that only changes in parts, you will be wasting a lot of time doing unnecessary I/O.

简单 2024-12-12 18:17:39

来自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. 目前tvOS上对本地用户默认没有限制
  2. ,在 512kB 时将发布警告通知,并在 1MB 时终止进程。
  3. 对于普遍存在的默认设置,限制取决于登录的 iCloud 用户。

From iOS SDK codes, and 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


    // ....
 }   

Summary

  1. Currently there is no limit for local user defaults
  2. On tvOS, where a warning notification will be posted at 512kB, and the process terminated at 1MB.
  3. For ubiquitous defaults, the limit depends on the logged in iCloud user.
梦毁影碎の 2024-12-12 18:17:39

每个人都回答了“有限制吗?”这个直接问题。然而,我发现这个帖子确实想要理解“在 UserDefaults 中存储多少才算太多?”

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

5个物体几乎没什么。你会没事的!


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


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

重要的是要记住:

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

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

Everyone has answered the direct question of "is there a limit?" However, I found this thread really looking to understand "how much is too much to store in UserDefaults?"

If you're looking for that answer, here's a useful thread. The responses I found helpful were to go to your project file and look at the plist file size:

5 objects is almost nothing. You'll be fine!


On my machine, I have about 28 megs of data in my user defaults. That's not causing any problems at all.


From general programming experience with arrays I would guess performance starts to rapidly decay when you get into 1000’s, depending on element size. Therefore in a program I wouldn’t have an issue storing a couple of hundred elements. This said I would probably start using a sqlite3 database or coredata, sooner rather than later if I were you.

Important to remember:

The above alleviated my concerns that my growing number of defaults (about 20-25 now) would cause problems. I use CoreData already, so I was considering which to use since my number of allowed user preferences/customizations is growing long. So, I'm going to stay with user defaults.

However, as other answers have pointed out, the file will be read and written as a whole. So reading 20 key/string dictionaries and 5 key/boolean dictionaries just to retrieve one string... not exactly ideal. Nonetheless, if it doesn't hurt performance and it saves you a ton of code, why not?

ˉ厌 2024-12-12 18:17:39

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

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

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

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

来自“iOS 应用程序能源效率指南”:

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

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

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

https://jeffreyfulton.ca/blog/2018/02/userdefaults-限制和替代方案

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

快乐编码!!!

As many already mentioned: I'm not aware of any SIZE limitation (except physical memory) to store data in a .plist (e.g. UserDefaults). So it's not a question of HOW MUCH.

The real question should be HOW OFTEN you write new / changed values... And this is related to the battery drain this writes will cause.

IOS has no chance to avoid a physical write to "disk" if a single value changed, just to keep data integrity. Regarding UserDefaults this cause the whole file rewritten to disk.

This powers up the "disk" and keep it powered up for a longer time and prevent IOS to go to low power state.

From "Energy Efficiency Guide for iOS Apps":

Minimize data writes. Write to files only when their content has changed, and aggregate changes into a single write whenever possible. Avoid writing out an entire file if only a few bytes have changed. If you frequently change small portions of large files, consider using a database to store the data instead.

READS are no problem, as all values are cached in memory.

EDIT: (July 2019): I just found this very good blog post by Jeffry Fulton.

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

He describes in detail the different aspects of the user defaults and also writes about some performance tests.

Happy Coding!!!

若言繁花未落 2024-12-12 18:17:39

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

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

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

As of iPadOS 13.1 beta 3, I'm now seeing the following message when trying to store a larger object (an image).

2019-09-14 11:01:29.634368+0100 MyApp[1686:147223] [User Defaults]
CFPrefsPlistSource<0x283c7d980> (Domain: com.example.MyApp, User:
kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents
Need Refresh: No): Attempting to store >= 4194304 bytes of data in
CFPreferences/NSUserDefaults on this platform is invalid. This is a
bug in MyApp or a library it uses

However retrieving the key appears to still work.

儭儭莪哋寶赑 2024-12-12 18:17:39

NSUserDefaults 中存储值没有限制。

There is No Limit for storing values in NSUserDefaults..

白龙吟 2024-12-12 18:17:39

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

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

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

The only Storage Limitation in NSUserDefaults is the Device Storage Capacity.

As much as there are available Storage Space in an iOS Device, you can practically store data in NSUserDefaults. The key-value pair is stored on a xml structured file (.plist) which is stored in an App Bundle.

The user defaults system and key-value store are both designed for
storing simple data types—strings, numbers, dates, Boolean values,
URLs, data objects, and so forth—in a property list. The use of a
property list also means you can organize your preference data using
array and dictionary types. It is also possible to store other objects
in a property list by encoding them into an NSData object first.

网白 2024-12-12 18:17:39

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

As far as my knowledge there is no limit for storing in NSUserdefaults.

眼眸印温柔 2024-12-12 18:17:39

无论驱动器上允许的最大文件大小如何。你可以用这段代码来检查一下!

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

It whatever the maximum allowed file size is on the drive. You can use this piece of code to check it out!

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文