I wanted to set default values for my application using a Settings.bundle and I ran into an interesting issue with iPhone SDK 2.2. If you don’t run the Settings application before your application runs for the first time, then the default settings are not set. It turns out that you’ll need to manually set them on the first time the application is run.

Setting defaults to the default value…

I’m not sure why there isn’t a function that can set the values for me, but after digging I found someone who ran into the same dilema. I don’t want to have multiple locations with default values (code and a Settings.bundle), so I found a programmatic way to set all the default values if they haven’t been set.

- (void)registerDefaultsFromSettingsBundle {
    NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    if(!settingsBundle) {
        NSLog(@"Could not find Settings.bundle");
        return;
    }
 
    NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
    NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
 
    NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
    for(NSDictionary *prefSpecification in preferences) {
        NSString *key = [prefSpecification objectForKey:@"Key"];
        if(key) {
            [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
        }
    }
    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
    [defaultsToRegister release];
}

All you have to do is call the above function if one of your Standard User Defaults returns null. Make the call once your application finishes loading like so:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
	// Get the application user default values
	NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
	NSString *server = [user stringForKey:@"server_address"];
	if(!server) {
		// If the default value doesn't exist then we need to manually set them.
		[self registerDefaultsFromSettingsBundle];
		server = [[NSUserDefaults standardUserDefaults] stringForKey:@"server_address"];
	}
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

References:

Tagged with:
 

23 Responses to iPhone Default User Settings Null?

  1. Chris says:

    Thanks Paul!

  2. cc says:

    thanks a lot, saved me some time and works great.

  3. Sami Shaio says:

    Thanks this is really helpful. One thing I had to change though is to check that the value for a default is not nil before setting it. Otherwise the app would crash if not all the defaults had non-nil values.

  4. Paul Solt says:

    You’re welcome!

    @SamiShaio I would try to avoid situations where it could be null, but that depends on what you’re doing. Keep your settings options simple for the Settings Bundle.

  5. Paul says:

    Great post. My updated app had been rejected with no explanation as to why from Apple, found out it was due to this. I will be referencing your article on my own blog shortly.

  6. Paul Solt says:

    awesome! I’m glad to have helped you.

  7. Gene says:

    Thanks Paul, a great post. I found this post while searching for the answer to a related issue. Not only did your post help resolve my other issue, it alerted me to one I hadn’t yet considered. – Gene, RIT Alumni ’80-’84

  8. Paul Solt says:

    Glad to hear back from an Alum!

  9. niclas says:

    Thanks! I have a lot of preferences so instead of checking them all for null I call your function before I read my defaults. Maybe a millisecond slower but much easier I think.

  10. Ted says:

    Thank you. Keep this post up for a long time. Kept getting nil and didn’t know why. My user defaults worked previously, but stopped working after I made changes to the plist. This solved the problem.

  11. Damien says:

    Great post, very helpful for when my app starts!
    Thanks.

  12. [...] must go to Paul Solt’s website for the useful piece of [...]

  13. poster says:

    dude, thanks! :-)

  14. Great and really helpful post. This issue still holds true even today, with the iOS 5.1 SDK.

  15. Paul Solt says:

    Hi Carlos,

    Glad to help!

    -Paul Solt

  16. John says:

    Hi I am new to this iPhone programming and i am not sure:

    a. Where to put the files? (in AppDelegate or ViewController)
    b. Error Use of undeclared identifier ‘window’, did you mean ‘_window’

    Please help?

    Keep up the great work :D

    Thanks
    John

  17. Paul Solt says:

    You can put it in your AppDelegate. Generally for “global” type settings you’ll initialize them when your app first launches.

    window is the AppDelegates reference to a window. Some of the newer code might do it differently (self.window or _window) The Xcode default project templates have changed since this article was first written.

  18. Dennis says:

    Nice post. Thanks for sharing your experience.

  19. Sachin says:

    Thanks so much Paul! very useful!

  20. Quang says:

    Thanks Paul! I can finally find the source of my problem. Great post!

  21. ashraf says:

    Should we call
    [[NSUserDefaults standardUserDefaults] synchronize];
    after this call?
    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];

    Otherwise it will not persist.

  22. Paul Solt says:

    Yes, sounds good. I think I did that elsewhere when I actually made changes.

    This code block was to load the “default” settings so your app had the proper values on first start.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>