Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any limit in storing values in NSUserDefaults?

People also ask

How much data can you store in NSUserDefaults?

It appears the limit is the maximum file size for iOS (logically), which is currently 4GB: https://discussions.apple.com/thread/1763096?tstart=0. The precise size of the data is circumscribed by the compiler types (NSData, NSString, etc.) or the files in your asset bundle.

Where are the NSUserDefaults values stored?

All the contents saved by NSUserDefaults is saved inside a plist file that can be found under Library -> Preferences -> $AppBundleId.

What types can you store natively in NSUserDefaults?

Types stored in NSUserDefaultsplist type can be stored by NSUserDefaults . These types are NSString(String) , NSArray(Array) , NSDictionary(Dictionary) (for both NSArray and NSDictionary types their contents must be property list objects), NSNumber(Int, Float, Double, Boolean) , NSDate and NSData .

Is NSUserDefaults secure?

Because NSUserDefaults stores all data in an unencrypted . plist file, a curious person could potentially view this data with minimal effort. That means that you should never store any type of sensitive data inside NSUserDefaults.


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).


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.


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?


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.

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!!!


There is No Limit for storing values in NSUserDefaults..


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.