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 i开发者_如何学编程ncur overhead. What is the preferred and most concise method for accessing preferences in any class?
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.
精彩评论