Cocoa Bindings and NSUserDefaults
Cocoa Bindings and NSUserDefaults
- Subject: Cocoa Bindings and NSUserDefaults
- From: Ben Haller <email@hidden>
- Date: Tue, 24 Nov 2009 21:17:06 -0500
Hi all! I've just implemented a trivial preferences panel using
Cocoa Bindings; it's my first use of bindings (have I mentioned I've
been living in a cave for the past five years? :->), so I'm hoping
the list is willing to take a quick look at my code and give me a
critique. I've got a few questions about it that I'll put after the
code.
Here we go. In my application delegate:
- (IBAction)orderFrontPreferences:(id)sender
{
[[AKPreferencesController sharedPreferencesController] showWindow:nil];
}
The AKPreferencesController class:
typedef enum {
akLaunchDoNothing = 0,
akLaunchShowNewSimulationPanel,
akLaunchShowBatchRunPanel
} AKLaunchAction;
@interface AKPreferencesController : NSWindowController
{}
+ (AKPreferencesController *)sharedPreferencesController;
+ (AKLaunchAction)launchAction;
+ (NSString *)sgeHeadNode;
+ (NSString *)sgeUsername;
+ (NSString *)sgePassword;
@end
------------------------------------------------------------------------------------------
#import "AKPreferencesController.h"
static NSString *akSGEHeadNodeKey = @"akSGEHeadNodeKey";
static NSString *akSGEUsernameKey = @"akSGEUsernameKey";
static NSString *akSGEPasswordKey = @"akSGEPasswordKey";
static NSString *akLaunchActionKey = @"akLaunchActionKey";
@implementation AKPreferencesController
+ (void)initialize
{
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:@"my.server.com" forKey:akSGEHeadNodeKey];
[dictionary setObject:@"username" forKey:akSGEUsernameKey];
[dictionary setObject:@"password" forKey:akSGEPasswordKey];
[dictionary setObject:[NSNumber
numberWithInt:akLaunchShowNewSimulationPanel] forKey:akLaunchActionKey];
[[NSUserDefaultsController sharedUserDefaultsController]
setInitialValues:dictionary];
}
+ (AKPreferencesController *)sharedPreferencesController
{
static AKPreferencesController *sharedPrefsController = nil;
if (!sharedPrefsController)
sharedPrefsController = [[AKPreferencesController alloc] init];
return sharedPrefsController;
}
+ (AKLaunchAction)launchAction
{
return (AKLaunchAction)[[[[NSUserDefaultsController
sharedUserDefaultsController] values] valueForKey:akLaunchActionKey]
intValue];
}
+ (NSString *)sgeHeadNode
{
return [[[NSUserDefaultsController sharedUserDefaultsController]
values] valueForKey:akSGEHeadNodeKey];
}
+ (NSString *)sgeUsername
{
return [[[NSUserDefaultsController sharedUserDefaultsController]
values] valueForKey:akSGEUsernameKey];
}
+ (NSString *)sgePassword
{
return [[[NSUserDefaultsController sharedUserDefaultsController]
values] valueForKey:akSGEPasswordKey];
}
- (id)init
{
if (self = [super initWithWindowNibName:@"AKPreferences"])
{
[self setShouldCascadeWindows:NO];
}
return self;
}
- (void)windowDidLoad
{
[[self window] center];
}
@end
So, very straightforward. The AKPreferences nib is what you'd
expect: a window with a radio control for the "launch action" with
tags set up to correspond to the enumeration, and three textfields for
the SGE head node, username and password strings. They are all bound
to the appropriate key paths on the shared user defaults controller.
It all works great, so I probably don't need to describe this in more
detail, post the nib, etc.; this is obviously a toddler's first
steps. :-> I've based this on mmalc's ControlledPreferences project
(thanks for that, mmalc!), and it was very quick to put together; I
certainly do see the benefits of bindings. But I do have a few
questions:
- There's a little bit of duplication of information between the nib
and the code. The tags on the radio button matrix's cells have to
match the values in the enumeration, for one thing. Even more
annoyingly, the strings for the defaults keys have to correspond to
the bindings key paths I enter in IB. This duplication seems like a
vulnerability (not that it wouldn't also be there without using
bindings, of course). There isn't any reasonable way to get rid of
this, is there?
- A little bit of glue code still seems to be necessary (or at least
aesthetic) to vend the user defaults to client code (i.e. the
+launchAction, +sgeHeadNode, etc. class methods). I could get rid of
them, but then I'd have to export the defaults keys in the header, and
every client of the preferences would have to do the same thing as
this glue code themselves, so the current way seems preferable (no pun
intended :->). Am I missing a way to make this code nicer, or will I
have to add a glue method like this every time I add a defaults key?
Apart from that, I'm curious whether anybody has anything else to
say about this code. Thanks!
Ben Haller
Stick Software
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden