[ Team LiB ] |
2.6 User DefaultsUser defaults is another term for user application preferences. Mac OS X has a well-designed user defaults system that is accessed in Cocoa through the Foundation class NSUserDefaults. Working with NSUserDefaults is similar to working with an NSDictionary. Default values are stored in the database by keys that the application developer defines in the application. The defaults database is actually a collection of property list files; every application has its own property list file where defaults are stored. You can view these files in ~/Library/Preferences. Defaults are organized into domains, which are groupings of default values that have varying degrees of visibility to applications. A domain is either persistent or volatile. Defaults in a persistent domain are stored in the defaults database, while defaults in a volatile domain are applicable only during the lifetime of the NSUserDefaults object that contains those values. NSUserDefaults has five standard domains:
When a default is requested, the domains are searched for the value in order, starting with NSArgumentDomain and ending with NSRegistrationDomain. The search ends at the first discovery of a default value. Thus, if many domains have values for the same default, NSUserDefaults returns the default that occurred in the higher-level domain. You can exploit the search order as a debugging aid by overriding any default by specifying a value in the NSArgumentDomain. User defaults are capable of storing only what property lists can store, namely NSData, NSNumber, NSString, NSDate, NSArray, and NSDictionary (although convenience methods are also provided to get and set scalar values). Using these data types, you can store information, such as dates, numbers, and text, as well as any object that is archiveable. Example 2-33 shows how to interact with the user defaults system. Example 2-33. Interacting with the user defaults system using NSUserDefaults// Create an instance of NSUserDefaults NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; // Store and retrieve a string [prefs setObject:@"Mike Beam" forKey:@"Author"]; NSString *author = [prefs stringForKey:@"Author"]; // Store and retrieve a number [prefs setFloat:1373.50 forKey:@"NASDAQ"]; [prefs setInt:2002 forKey:@"Year"]; float level = [prefs floatForKey:@"NASDAQ"]; int year = [prefs intForKey:@"Year"]; // Store and retrieve dates [prefs setObject:[NSDate date] forKey:@"Last Opened"]; NSDate *lastOpenDate = [prefs objectForKey:@"Last Opened"]; // Store collections [prefs setObject:dictionary forKey:@"A Dictionary"]; [prefs setObject:array forKey:@"An Array"]; // Retrieve collections NSArray *array = [prefs arrayForKey:@"An Array"]; NSDictionary *dict = [prefs dictionaryForKey:@"A Dictionary"]; // Use the following if you want mutable objects... NSMutableArray *mArray = [NSMutableArray arrayWithArray: [prefs arrayForKey:@"An Array"]]; NSMutableDictionary *mDict = [NSMutableDictionary dictionaryWithDictionary: [prefs dictionaryForKey:@"A Dictionary"]]; All applications should establish factory default settings in the registration domain. This is done with the registerDefaults method. Establishing defaults in the registration domain often takes place in an overridden initialize class method of one of the first classes loaded in your application. This method works well because it is used to initialize classes when they are first loaded by the runtime system, and it is thus one of the earliest entry points in code execution. This example shows how it might be done for a small number of defaults: + (void)initialize { NSUserDefaults *prefs; NSMutableDictionary *defs; prefs = [NSUserDefaults standardUserDefaults]; [defs setObject:@"May" ForKey:@"Month"]; [defs setInteger:2002 ForKey:"Year"]; [prefs registerDefaults:defs]; } If you need to register a large number of defaults, hardcoding them this way might prove cumbersome. For these situations, it may be more convenient to store factory settings in a property list included with the application, which is then read into a dictionary and registered with user defaults: + (void)initialize { NSString *prefsFile; NSUserDefaults *prefs; NSDictionary *defs; // The factory defaults file is a resource in the application // bundle. The path is retrieved using NSBundle. prefsFile = [[NSBundle mainBundle] pathForResource:@"FactoryDefaults" ofType:@"plist"]; defs = [NSDictionary dictionaryithContentsOfFile:prefsFile]; prefs = [NSUserDefaults standardUserDefaults]; [prefs registerDefaults:defs]; } One commonly stored preference is an NSColor. There are, however, no provisions for storing a color directly in the defaults database. One way to store information about colors in the defaults database is to store the color space name and a dictionary of the color component values.. All of these data types are supported by NSUserDefaults. A better solution is to archive the NSColor object into an NSData instance and store it in the preferences, as shown in Example 2-34. Example 2-34. Storing an NSColor to user defaults// Assume NSColor object color exists // Store the color NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; NSData *colorData; colorData = [NSArchiver archivedDataWithRootObject:color]; [prefs setObject:colorData forKey:@"Text Color"]; // Retrieve the color colorData = [prefs dataForKey:@"Text Color"]; id color = [NSUnarchiver unarchiveObjectWithData:colorData]; This technique is not limited to only NSColor. It can work with any class of object that conforms to the NSCoding protocol, the prerequisite for compatibility with Foundation's archiving system. |
[ Team LiB ] |