Many applications have Preferences panels that allow the user to choose a preferred appearance or behavior. The user's choices go into the user defaults database in the user's home directory. Note that only the choices that vary from the factory defaults are saved in the user defaults database. If you go to ~/library/Preferences,you can see your user defaults database. The files are in property List format; you can browse through them with Property List Editor.
The NSUserDefaults class allows your application to register the factory defaults,save the user's preferences,and read prevIoUsly saved user preferences.
NSUserDefaults
Every application comes with a set of defaults from the factory. When a user edits his or her defaults,only the differences between the user's wishes and the factory defaults are stored in the user's defaults database. Thus,every time the application starts up,you need to remind it of the factory defaults. This operation is called registering defaults.
After registering,you will use the user defaults object to determine how the user wants the app to behave. This process is called reading and using the defaults. The data from the user's defaults database will be read automatically from the filesystem.
You will also create a Preferences panel that will allow the user to set the defaults. The changes to the defaults object will be written automatically to the filesystem. This process is kNown as setting the defaults (Figure 13.3).
Here are some commonly used methods that are implemented in NSUserDefaults:
Precedence of Different Types of Defaults+ (NSUserDefaults *)standardUserDefaults
Returns the shared defaults object.
- (voID)registerDefaults:(NSDictionary *)dictionary
Registers the factory defaults for the application.
- (voID)setBool:(BOol)value forKey:(Nsstring *)defaultname- (voID)setfloat:(float)value forKey:(Nsstring *)defaultname- (voID)setInteger:(int)value forKey:(Nsstring *)defaultname- (voID)setobject:(ID)value forKey:(Nsstring *)defaultname
Methods for changing and saving a user's wishes.
- (BOol)boolForKey:(Nsstring *)defaultname- (float)floatForKey:(Nsstring *)defaultname- (int)integerForKey:(Nsstring *)defaultname- (ID)objectForKey:(Nsstring *)defaultname
Methods for reading the defaults. If the user hasn't changed them,the factory defaults are returned.
- (voID)removeObjectForKey:(Nsstring *)defaultname
Removes the user's preference,so that the application will return to using the factory defaults.
So far,we have talked about two levels of precedence: What the user writes to his or her defaults database overrIDes the factory defaults. In fact,several more levels of precedence exist. These levels of default settings are kNown as domains. Here are the domains used by an application,from highest to lowest priority:
Arguments: Passed on the command line. Most people start their applications by double-clicking on an icon instead of by working from the command line,so this feature is seldom used in a production app.
Application: What comes from the user's defaults database.
Global: What the user has set for his or her entire system.
Language: What is set based on the user's preferred language.
Registered defaults: The factory defaults for the app.
Creating Keys for the names of the Defaults
You will be registering,reading,and setting defaults in several classes in your application. To make sure that you always use the same name,you should declare those strings in a single file and then simply #import that file into any file in which you use the names.
There are several ways to do this. For example,you Could use the C preprocessor's #define command,but most Cocoa programmers use global variables for this purpose. Add the following lines to your PreferenceController.h file after the#import statement:
extern Nsstring * const BNRtableBgcolorKey;extern Nsstring * const BNREmptyDocKey;Now define these variables in PreferenceController.m. Put them after the #import lines but before @implementation :
Nsstring * const BNRtableBgcolorKey = @"tableBackgroundcolor";Nsstring * const BNREmptyDocKey = @"EmptydocumentFlag";Why would you declare global variables that simply contain a constant string? After all,you Could simply remember what the string was and type it in whenever you need it. The problem is that you might misspell the string. If the string is surrounded by quotes,the compiler will accept the misspelled string. In contrast,if you misspell the name of a global variable,the compiler will catch your error.
To keep the global variables from conflicting with another company's global variables,you have prefixed them with BNR (for Big Nerd Ranch). Global variables from Cocoa are prefixed with NS. These prefixes are important only when you start using classes and frameworks developed by third partIEs. (Note that class names are also global. You might prefer to prefix all your class names with BNR to keep them from conflicting with anyone else's classes.)
Registering Defaults
Each class is sent the message initialize before any other message. To ensure that your defaults are registered early,you will overrIDe initialize in AppController.m:
+ (voID)initialize{ // Create a dictionaryNSMutableDictionary *defaultValues = [NSMutableDictionary dictionary];
// Archive the color object
NSData *colorAsData = [NSKeyedArchiver archivedDataWithRootObject:
[NScolor yellowcolor]];
// Put defaults in the dictionary
[defaultValues setobject:colorAsData forKey:BNRtableBgcolorKey];
[defaultValues setobject:[NSNumber numberWithBool:YES]
forKey:BNREmptyDocKey];
// Register the dictionary of defaults
[[NSUserDefaults standardUserDefaults]
registerDefaults: defaultValues];
NSLog(@"registered defaults: %@",defaultValues);
}
Because this is a class method,its declaration is prefixed with +.
Note that we had to store the color as a data object. NScolor objects do not kNow how to write themselves out as property List,so we pack them into a data object that does. The property List classes—Nsstring, NSArray,monospace; Font-size:14px">NSDictionary,NSCalendarDate,monospace; Font-size:14px">NSData,and NSNumber—do kNow how to write themselves out as property Lists. A property List comprises any combination of these classes. For example,a dictionary containing arrays of dates is a property List.
Letting the User Edit the Defaults
Next,you will alter the PreferenceController class so that the Preferences panel will cause the defaults database to get updated. Declare the following methods in PreferenceController.h:
- (NScolor *)tableBgcolor;- (BOol)emptyDoc;Make your PreferenceController.m file look like this:
Code VIEw:#import "PreferenceController.h"
Nsstring * const BNRtableBgcolorKey = @"tableBackgroundcolor";
Nsstring * const BNREmptyDocKey = @"EmptydocumentFlag";
@implementation PreferenceController
- (ID)init{
if (![super initWithWindowNibname:@"Preferences"])return nil;return self;
}- (NScolor *)tableBgcolor{ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSData *colorAsData = [defaults objectForKey:BNRtableBgcolorKey]; return [NSKeyedUnarchiver unarchiveObjectWithData:colorAsData];}- (BOol)emptyDoc{ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; return [defaults boolForKey:BNREmptyDocKey];}- (voID)windowDIDLoad
{
[colorWell setcolor:[self tableBgcolor]];
[checkBox setState:[self emptyDoc]];
}- (IBAction)changeBackgroundcolor:(ID)sender
NScolor *color = [colorWell color];
NSData *colorAsData =
[NSKeyedArchiver archivedDataWithRootObject:color];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setobject:colorAsData forKey:BNRtableBgcolorKey];
}
- (IBAction)changeNewEmptyDoc:(ID)sender{
int state = [checkBox state];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:state forKey:BNREmptyDocKey];
@end
In the windowDIDLoad method,you are reading the defaults and making the color well and check Box reflect the current settings. In changeBackgroundcolor: and changeNewEmptyDoc:
You should Now be able to build and run your application. It will read and write to the defaults database,so the Preferences panel will display the last color you chose and indicate whether the check Box was on or off. You have not,however,done anything with this information yet,so the unTitled document will continue to appear,and the background of the table vIEw will continue to be white.
Using the DefaultsNow you are going to use the defaults. First,you will make your AppController become a delegate of the NSApplicationobject and suppress the creation of an unTitled document,depending on the user defaults. Then,in Mydocument Suppressing the Creation of UnTitled documents
As before,there are two steps to creating a delegate: implementing the delegate method and setting the delegate outlet to point to the object (Figure 13.4).
Before automatically creating a new unTitled document,the NSApplication object will send the messageapplicationShouldOpenUnTitledfile: to its delegate. In AppController.m,add the following method:
- (BOol)applicationShouldOpenUnTitledfile:(NSApplication *)sender{NSLog(@"applicationShouldOpenUnTitledfile:"); return [[NSUserDefaults standardUserDefaults] boolForKey:BNREmptyDocKey];}
@L_419_78@To make your AppController the delegate of the NSApplication object,open the MainMenu.nib file,and Control-click file's Owner—which represents the NSApplication object—to bring up its connection window. Drag from delegate to yourAppController (Figure 13.5).
Figure 13.5. Select the delegate Outlet
Setting the Background color on the table VIEw
After the nib file for a new document window has been successfully unarchived,your Mydocument object is sent the messagewindowControllerDIDLoadNib:. At that moment,you can update the background color of the table vIEw.
You should already have this method in Mydocument.m; simply edit it to look like this:
- (voID)windowControllerDIDLoadNib:(NSWindowController *)aController{ [super windowControllerDIDLoadNib:aController]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *colorAsData;
colorAsData = [defaults objectForKey:BNRtableBgcolorKey];
[tableVIEw setBackgroundcolor:
[NSKeyedUnarchiver unarchiveObjectWithData:colorAsData]];
Also,make sure that you import PreferenceController.h at the beginning of Mydocument.m so that you can use the global variables that are declared there.Build and run your application.
For the More CurIoUs: NSUserDefaultsController
Sometimes,you will want to bind to a value from the NSUserDefaults object. An NSUserDefaultsController class makes this possible. All the nibs in your application will use a single shared instance of NSUserDefaultsController.
For example,if you wanted to use bindings,instead of target/action,to deal with the check Box on the Preferences panel,you would bind it to the shared NSUserDefaultsController's value.EmptydocumentFlag (Figure 13.6).
figure 13.6. Binding to the NSUserDefaultsController[View full size image] 总结
以上是内存溢出为你收集整理的Cocoa Programming for Mac OS X 第十三章(User Defaults)摘录全部内容,希望文章能够帮你解决Cocoa Programming for Mac OS X 第十三章(User Defaults)摘录所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)