There are lots of nice resources (both printed and online) regarding the use of the
Settings.bundle to store the user’s preferences on the iPhone, but there seems to be a severe lack of resources about not using it.
Settings.bundle is admittedly pretty cool. With a single
.plist file you can create a settings management page in your application that covers a number of common requirements. But besides the obvious UI concern of storing your application’s preferences in a location many of your users will never check, the bigger problem is one of limitations; if the
Settings.bundle does what you need, great. If it doesn’t, get the hell out—you can’t put any custom code into the Settings app.
Need to make a query to determine the options for a setting? Not happening. Multi-line text entry? Sorry.
With Raconteur I happily used
Settings.bundle in version 1.0 and then hit a brick wall when adding password protection because there’s no way to do password confirmation in the Settings app. And surely I’m not going to leave my application’s settings arbitrarily (from a user’s perspective) split between inside and outside the application, so I have to backtrack and move everything in.
My advice for developers starting on new applications is don’t use
Settings.bundle. Unless you know all of your requirements upfront and they couldn’t possibly change (and if you do, I’d like to visit your mythical waterfall). On the whole, it’s exceedingly anti-agile to hit a brick wall and have to redo work. Not to mention breaking user expectations for everyone who had already found the external settings.
Now, if you’re not using the
Settings.bundle mechanism, how do you store your user’s preferences? I imagine this is exceeding obvious to experienced Cocoa programmers, but to developers starting with the iPhone, the docs aren’t so clear… the
NSUserDefaults mechanism works the same whether you are using
Settings.bundle or not. Just grab the defaults object, register some default defaults (…), and start using them:
1 2 3 4 5
Note that this
registerDefaults call is important whether you use
Settings.bundle or not. You might be shocked (I know I was) to find that your application’s settings (and associated defaults) from your
Settings.bundle might not be programmatically available until the user runs the Settings app. Which means that you probably set the defaults once in the
Settings.bundle and now you get to set them again in code. I know, lame.
Access your settings like so:
1 2 3 4
A few more tips:
- Definitely consider defining some constants for your preference keys so that the compiler can find your typos instead of your users finding them.
NSUserDefaultsacts like an
NSMutableDictionary, it only stores objects (not your
ints, etc.). Fortunately it provides nice convenience methods like
setBool:forKey:to abstract away conversions to object types (like boolean
- You can use both
Settings.bundleand your own interface to access the exact same preference data with no problems (makes sense but I’m just pointing it out). That said, it probably doesn’t make a great deal of sense from a UI perspective.
NSUserDefaultsis automagically saved off at regular intervals (and, I think, when you exit the application). You don’t have to worry about saving those preferences, or about exactly where they go. That’s why it’s automagic.
- Once you remove
Settings.bundlefrom the program, it may still appear to be around, showing up in the
Settingsapp. In reality it won’t hang around on your users’ devices (I believe), but to remove it from your test devices, simply make sure to run
Clean All Targetsin Xcode.