Is there any limit in storing values in NSUserDefaults?

37,947

Solution 1

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

Solution 2

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.

Solution 3

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.

Solution 4

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?

Solution 5

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

Share:
37,947

Related videos on Youtube

Johnykutty
Author by

Johnykutty

iOS developer (Swift/ObjectiveC) Opensource fan

Updated on July 05, 2022

Comments

  • Johnykutty
    Johnykutty almost 2 years

    I am new to iPhone development and objective C. I have used NSUserDefaults to store some values in my app. But I don't know that if there is any limit for storing values in NSUserDefaults. Can anyone help me to know that.

    Thanks in advance.

    • Bobby
      Bobby almost 7 years
      NSUserDefaults is intended for relatively small amounts of data, queried very frequently, and modified occasionally. Using it in other ways may be slow or use more memory than solutions more suited to those uses. Currently there is no limit for local user defaults except on tvOS. I found this information by "cmd click" on UserDefaults which takes you to their source file. I read the documentation looking for this information, but couldn't find it there.
    • TheTiger
      TheTiger about 6 years
      I'm not sure but you can see this link.
  • MobileVet
    MobileVet over 9 years
    The point about this being a single file is quite critical. Very good information, thanks.
  • Stonz2
    Stonz2 about 8 years
    FYI int values don't go that high, so you'll end up with an overflow (assuming you make it past ~2.15B iterations) in your loop. Before that though, you'll end up overflowing sizeOfFile.
  • iDeveloper
    iDeveloper about 6 years
    Is there any impact on device performance after add big files/Data ?
  • TheTiger
    TheTiger about 6 years
    Might be true but see this link. What is correct?
  • SAHM
    SAHM over 4 years
    I am having this issue too! Have you found the cause/solution?
  • Doug
    Doug over 4 years
    @SAHM Not sure re the cause. As I was simply saving a single image as a user preference, I ended up writing the data to the documents folder instead of using user defaults.
  • SAHM
    SAHM over 4 years
    Out of curiosity, @Doug, were you using "synchronize" after saving?
  • SAHM
    SAHM over 4 years
    I have some thoughts about this if you want to chat.
  • Doug
    Doug over 4 years
    @SAHM Nope I wasn’t calling synchronize. As stated in the docs, “this method is unnecessary and shouldn't be used.”
  • SAHM
    SAHM over 4 years
    I thought calling synchronize might actually have caused the problem at the time I wrote this. Since then, I think I read somewhere, though it might have been an old thread or old documentation, that individual values stored shouldn’t be more than 4kB.
  • Arjun
    Arjun over 2 years
    I'm getting this error: Attempting to store >= 4194304 bytes of data in CFPreferences/NSUserDefaults on this platform is invalid. This is a bug in App or a library it uses
  • Arjun
    Arjun over 2 years
    I'm getting this error: 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