This blog has moved to rhult.github.com

Registering defaults for NSUserDefaults using a property list

Thursday, April 9, 2009
In a previous post about using property lists, I wrote a little about property lists and a use case I had for them. Another one I ran in to recently is related to user defaults:

NSUserDefaults is the system in Mac OS X that handles user preferences. Applications usually register default values at launch time, so that all preferences have a sane default value in case the user hasn't set one for a particular preference. Most examples I've found on the subject do something along the lines of:

// Register user defaults in the class initializer.
+ (void)initialize
{
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
@"YES", @"ShowToolBar",
@"NO", @"AutoSaveEnabled",
// ... lots of objects and keys here,
nil];

[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
}


However, if you have many keys, or just want to make it possible to change them without recompiling, they can be managed through a property list file instead of doing it programmatically. To do that, first create a property list by selecting File → New File... or pressing cmd-N in Xcode and selecting Property List in the Other category. Then add the default values using the property list editor.

Assuming the plist file is named UserDefaults.plist, the code can then be changed to:

+ (void)initialize
{
NSString *defaultsPath = [[NSBundle mainBundle] pathForResource:@"UserDefaults"
ofType:@"plist"];
NSDictionary *appDefaults = [NSDictionary dictionaryWithContentsOfFile:defaultsPath];

[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
}

Using property lists

Wednesday, April 8, 2009
Before entering the Cocoa world, whenever I needed to store and retrieve some small amount of data in an application, I usually handcrafted an XML format and wrote a matching XML parser using either DOM or SAX. This often meant a lot of uninspiring code duplication. On Mac OS X, there is a standardized format that is used throughout the system called property list or "plist". Not only are there APIs to parse plists into the familiar data structures in Cocoa, but there is also a builtin editor for plists in Xcode.

This came in handy recently in some code I was working on. I needed to store 20 or 30 pairs of strings and select one pair randomly from time to time. Instead of entering the strings in the code, they were put into a plist file.

Create and edit a plist
It's easy to create a property list. In Xcode, just select File → New File... or press cmd-N, and select the template Property List in the Other category. Then add the data you wish to, using the property list editor in Xcode. You can of course also handwrite the XML using any text editor.

Use the data
Assume that the property list is structured with a top-level key called Pairs, whose value is an array of our string pairs. Each pair in turn is also an array, with two strings in each. The code to read the list could then look as follows:

- (void)readStringPairs
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"MyFileName"
ofType:@"plist"];
NSDictionary *toplevelDict =
[NSDictionary dictionaryWithContentsOfFile:path];

// Get the array of pairs, retain it as we need it later.
pairs = [[toplevelDict valueForKey:@"Pairs"] retain];
}

- (void)randomizeStrings
{
// Get a random pair, represented by an array.
NSArray *pair = [pairs objectAtIndex:arc4random() % [pairs count]];

// Get the two strings.
NSString *name = [pair objectAtIndex:0];
NSString *description = [pair objectAtIndex:1];

// Do something with the strings here.
}


If you need something a little bit more flexible or complex, you can nest dictionaries and arrays in the plist as well. As a matter of fact, my original code doesn't only have two strings per pair, but one string and an array of strings.

About me

Welcome to my blog about programming, primarily on Mac OS X using Cocoa and related technologies. I plan to write about problems I encounter, interesting APIs I run into, or simply tips and tricks that I think are worth sharing.

I am quite new to application development on Mac, coming from the GNOME community where I have been developing and maintaining various pieces of software for roughly ten years. Being a maintainer of the native Mac port of GTK+ for a couple of years led me into the direction of Cocoa which finally got me hooked.