12

During a logic process in my app, I need to access the user preferences frequently, and a bunch of times 10~15 to determine what needs to be processed and how. May this question is not about performance, but about doing it correctly.

Currently I'm doing a [[NSUserDefaults standardUserDefaults] valueForKey:...] each time I need to request a value. Is this correct? I think that "saving" the user defaults as an ivar could reduce extra work, but then I wonder if this won't have sync problems, like if the user changes the preferences and they get updated only if the app is restarted (so the user defaults object is recreated).

Is there any better way?

sidyll
  • 57,726
  • 14
  • 108
  • 151
  • 1
    You won't have sync problems if you do and you won't have performance issues if you don't. – vakio May 24 '11 at 18:13

3 Answers3

27

Don't worry about it, it's extremely fast and I do not believe there is a better way, it's the way the class is meant to be used.

The NSUserDefaults class caches the values internally so the lookup is extremely fast. The overhead of [NSUserDefaults standardUserDefaults] vs an instance variable is so small that you wouldn't even notice it if you did it 5 million times in your code.

The only proper way of optimising this would be by improving your logic, caching the values you're using yourself with a pointer rather than the dictionary that NSUserDefaults basically is etc.

Antwan van Houdt
  • 6,989
  • 1
  • 29
  • 52
  • I believe you're right (the caching is explicit in the documentation) but your assertion sounds a bit extreme, anything to back it up? – Clafou Jan 30 '13 at 11:29
  • 4
    @Clafou re-reading what I posted here my comment didn't actually answer your question but only strengthened the 'yes yes berieve me!' implication my answer had, sorry for that. Anyway, testing it gave me around 150ms for accessing the shared instance 5 million times. Screenie: http://cl.ly/image/3J1J0H3D2h26 http://cl.ly/image/0F3R18413H2f – Antwan van Houdt Nov 22 '14 at 13:42
  • Isn't there a cost to doing a String lookup instead of accessing an instance variable? You must allocate and create the String and then use it to look up the value (probably with a hash table). Surely *this* has a performance hit vs. an instance variable. – BallpointBen Jul 16 '17 at 18:16
  • 1
    @BallpointBen Yes I wouldn't recommend doing this in performance critical applications. However; in most use cases a few byte allocation and hashtable looking is not a performance hit compared to other things in your application. Optimising the hell out of small things is rarely a good idea or the bottleneck. – Antwan van Houdt Jul 17 '17 at 10:27
4

You won't have any problem if you save the defaults object to an ivar. Notice it's a singleton and its pointer won't change.

arclight
  • 5,299
  • 1
  • 22
  • 26
  • Assumedly he meant saving the *value* of the preference to an in-memory ivar, so it would not need to be continually read from the key in NSUserDefaults. Not saving a (shorter) variable name such as `NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];`. – pkamb Nov 18 '15 at 01:37
2

Do the values in the user defaults change over time during this logic process?

If not, you could access each value that you'll need throughout the process once at the start and store the results in local variables.

Then you can use those variables as many times as you like without having to hit the user defaults reading the data each time.

However, if those values are being changed while your logic process is ongoing, then accessing them from the defaults is probably the only way.

In terms of performance, accessing it 10-15 times isn't going to have any adverse effect. If you were accessing it 10-15 times per second for a prolonged period of time, then you might encounter some responsiveness issues.

Jasarien
  • 58,279
  • 31
  • 157
  • 188
  • "If you were accessing it 10-15 times per second for a prolonged period of time, then you might encounter some responsiveness issues." <--- 10 to 15 times a second is peanuts for a computer. BTW in the documentation it states: "UserDefaults caches the information to avoid having to open the user's defaults database each time you need a default value", so you probably do orders of magnitude more reads per seconds before you notice anything. – Toad Mar 25 '19 at 07:54