views:

113

answers:

3

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?

+3  A: 

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.

Preston
Thank you. I would not like to use a theme object to pass around as this would involve declaring, synthesizing etc. a property for it in each class that want to use it. I was hoping for a solution that would involve something like a preference class that I could simply import and then access the preferences stored like one would access constants stored in a header file. Perhaps a singleton class would achieve this?
Run Loop
You're already accessing a shared preferences object with +standardUserDefaults. As for theme objects, I wasn't talking about setting it as a property in each class. Instead, each class's output method could take a theme object as an argument, such as -(NSAttributedString *)outputUsingTheme:(MyTheme *)aTheme. A central controller could store the theme as a property and pass it to each class's output method, appending each result to the final output for presentation to the user.
Preston
+1  A: 

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.

zoul
Thanks, but what you are suggesting will require 4 lines of code per class (variable declaration, property declaration, synthesization, release) in addition to assigning the preferences to the class in the first place. Creating a local variable for the preferences is beginning to look like the most attractive option.
Run Loop
A: 

The most concise method is to assign values in the StandardUserDefaults dictionary to local variables during object initialization.

Run Loop