Best practice - Accessing preferences globally

User preferences for my app is store in NSUserDefaults. This includes a "theme" preference, which needs to be accessed frequently by multiple classes. I would prefer not to call "[[NSUserDefaults standardUserDefaults] objectForKey:..." repeatedly as it makes for inconcise code and I assume will incur overhead. What is the preferred and most concise method for accessing preferences in any class?

Answers


The preferred way to access user preferences is the way you're doing it, which is hardly inconcise. You shouldn't assume overhead until it's actually noticed.

That said, consider reading the theme value from user preferences once on startup and then storing the respective theme settings in a theme object. You could then pass this theme object to the various classes when you call their methods, and they could just use that. As a bonus, you end up being able to pass them arbitrary theme objects regardless of user setting, allowing you to use their output for theme previewing in a theme selection interface, assuming these classes involve user-visible output. Just something to consider.


The overhead is so small it does not matter at all. The rest is a question of design and balance. The “right” way to solve this issue from the design viewpoint is to make the dependency on the user defaults visible by exposing an outlet in the class interface:

@interface ClassThatUsesSomethingFromDefaults : NSObject {
    NSUserDefaults *prefs;
}

@property(retain) NSUserDefaults *prefs;

This way it’s clear that the behaviour of this class varies with user defaults, which is a good thing. It also makes it easier for you to work with the defaults in the class (calling prefs instead of [NSUserDefaults standardUserDefaults]). And it makes it easier to isolate the class from the rest of the system – you can use the class without defaults, supply a stub defaults object or anything like that.

The downside to this solution is that you have to rethink the way you wire your objects together. Which really is an upside. The dependencies such as prefs have to be supplied to your object “from the outer world,” like from the Interface Builder or some kind of factory class. (As I stated at the beginning, it’s a question of balance. If you have just one preference string it’s probably not worth it to build all this to get the single string.)

Singletons are the devil’s way to solve this – read the Singletons are Pathological Liars blog post by Miško Hevery and the blog posts linked from there.


UPDATE: Calling [NSUserDefaults standardUserDefaults] introduces no additional overhead, although it may not be the most concise. The only time it may not be the most concise is when complex object are contained in a preference e.g. a dictionary or an array - in that case you may wish to assign to a local variable upon initialization.


Need Your Help

Remove dom elements by matching href with javascript

javascript dom

I need to remove some 'a tags' that have img's in them only if the a href matches exactly. This is the code that needs to be removed-

Converting multi-page PDFs to several JPGs using ImageMagick and/or GhostScript

pdf imagemagick jpeg ghostscript

I am trying to convert a multi-page PDF file into a bunch of JPEGs, one for each page in the PDF. I have spent hours and hours looking up how to do this, and eventually I discovered that I need