Online Book Reader

Home Category

iOS Recipes - Matt Drance [75]

By Root 229 0

setter=prp_setUsername:) NSString *prp_username;

@end

But user defaults can still be tricky, especially with scalars like booleans and integers; undefined values still evaluate to something (specifically NO or 0). How can we tell whether the user actually set a value of 0 or whether the default simply doesn’t exist? What if we want an explicit default value when nothing has been set by the user? Let’s say we have a boolean to determine whether we should enable a data cache:

BOOL useCache = YES;

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

if ([defaults objectForKey:PRPDefaultsKeyCaching]) {

useCache = [self boolForKey:PRPDefaultsKeyCaching];

}

This code declares a local boolean and sets it to the desired default behavior of YES to enable caching. It then checks for the existence of an object for the PRPDefaultsKeyCaching key, and if one exists, it uses that boolean value. If we blindly called -[NSUserDefaults boolForKey:], then useCache would evaluate to NO in the case of an empty setting, which is not what we want.

So, enforcing default behavior for user defaults is not a lot of work. But once we have to reference this value from multiple places, the previous logic needs to be duplicated, which opens the door for careless bugs and refactoring challenges. If we decide to change the default behavior, we need to hunt down every place this code is used. We can solve this problem with the -[NSUserDefaults registerDefaults] method, which allows you to pass some baseline values for any desired keys. This way, your consumer code isn’t burdened with nil checks when fetching a specific key.


Ensuring “Default Defaults” Are Installed

If you use ‑registerDefaults to set baseline values for your user defaults, make sure you do it very early. The first line of your application delegate’s application:didFinishLaunchingWithOptions: method is a good place for that, but even that may not be as soon as you think. Objects in your MainWindow.xib file, for example, may be initialized before your app delegate receives that message. If those objects expect the defaults to be in place, you could run into problems. Test thoroughly to make sure none of these surprises lies waiting in your application.


Note that ‑registerDefaults is part of Apple’s API: you can use it with or without the category technique discussed in this recipe. In the SmartUserDefaults project accompanying this chapter, it is sent from ‑applicationDidFinishLaunching:. The defaults are loaded from a property list—DefaultPrefs.plist—that is bundled inside the app.

SmartUserDefaults/iPad/AppDelegate_iPad.m

- (BOOL)application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

[super registerDefaults];

[window makeKeyAndVisible];

return YES;

}

SmartUserDefaults/Shared/DemoAppDelegate.m

- (void)registerDefaults {

NSString *prefs = [[NSBundle mainBundle] pathForResource:@"Prefs"

ofType:@"plist"];

NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:prefs];

NSDictionary *defaults = [dict valueForKey:@"defaults"];

[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];

[[NSUserDefaults standardUserDefaults] synchronize];

}

You can see the effects of this step by launching the SmartUserDefaults project. Note that on first launch, the “Caching” switch is set to on, even though the view controller code merely reads from the user defaults to set the switch. This is because the dictionary we passed to ‑registerDefaults had a default value of YES for prp_cachingEnabled. Any changes made to the switches or text field (after hitting the Return key) are recorded in the user defaults so you can compare your settings to the original values.

SmartUserDefaults/Shared/DemoViewController.m

self.cacheSwitch.on = defaults.prp_cachingEnabled;

SmartUserDefaults/NSUserDefaults+PRPAdditions.m

- (BOOL)prp_isCachingEnabled {

return [self boolForKey:PRPDefaultsKeyCaching];

}

This recipe gets you started on the right foot with NSUserDefaults with every project, centralizing

Return Main Page Previous Page Next Page

®Online Book Reader