Default values on first launch #68

Closed
ghost opened this Issue Jun 24, 2011 · 10 comments

Projects

None yet

5 participants

@ghost

It seems default values in my plist aren't available on a freshly installed version of my app. For example a toggle switch with default value set to YES results in a NO value until the user actually switches the toggle. I guess that's because default values from the plist aren't written to the settings storage upon first launch. If I'm right, what's the best way to deal with this? Thanks!

P.S. is this the right way to read a value?
[appSettingsViewController.settingsStore boolForKey:@"myKey"]

@futuretap
Owner

Create a userDefault.plist in your Bundle. Then register it like that in your -applicationDidFinishLaunching::

// Load the default values for the user defaults
NSString* pathToUserDefaultsValues = [[NSBundle mainBundle]
                                      pathForResource:@"userDefaults" 
                                      ofType:@"plist"];
NSDictionary* userDefaultsValues = [NSDictionary dictionaryWithContentsOfFile:pathToUserDefaultsValues];

// Set them in the standard user defaults
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValues];

This creates a default set of settings if started the first time.

@futuretap
Owner

Wrt your P.S.: just use good old [[NSUserDefaults standardUserDefaults] boolForKey:@"myKey"]

@ghost

Do I have to create a separate file for this, or is there a way to use the default values from the settings plist directly?

@futuretap
Owner

You need a separate file.

Would be an interesting idea to generate it from the settings plist. Not easy, though. Especially with all the overriding plists (inApp, ~iphone/~ipad and so on).

@ghost

Alright, luckily I don't have a lot of settings so it's not a problem. But yeah, reading it from the settings plist would be cool indeed :) Thanks!

@ghost ghost closed this Jun 24, 2011
@DoctorG

Thanks for answering this. It was driving me nuts.

@pelamfi

There is a discussion on this in stackoverflow.com http://stackoverflow.com/q/6667911/1148030 and plenty of code samples on how to implement this neatly.

@cpdigger

We think it would be a nice thing if the framework scan all DefaultValues in the bundle plist and then use NSUserDefault registerDefaults to tell it to IOS. A separate file in the bundle won't be a good aproach :(

@futuretap
Owner

@cpdigger agree, would be nice to have. It's not trivial to write though as I mentioned before. Wanna contribute? ;-)

@fabiosoft

This works like a charm, even with multiple nested plist files :)

- (void)registerDefaultsFromSettingsBundle{
    // standard stored preference values
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    // settings files to process
    NSMutableArray *preferenceFiles = [[NSMutableArray alloc] init];
    // begin with Root file
    [preferenceFiles addObject:@"Root"];
    // as other settings files are discovered will be added to preferencesFiles
    // init IASKSettingsReader for current settings file
    IASKSettingsReader *settingsReader = [[IASKSettingsReader alloc]initWithFile:[preferenceFiles lastObject]];
    [preferenceFiles removeLastObject];
    //filter only plist files from the settings bundle
    NSError *error;
    NSArray *fileinbundle = [[NSFileManager defaultManager]
                             contentsOfDirectoryAtURL:[[settingsReader settingsBundle] resourceURL] includingPropertiesForKeys:@[]
                             options: NSDirectoryEnumerationSkipsHiddenFiles|NSDirectoryEnumerationSkipsSubdirectoryDescendants
                             error:&error];
    NSPredicate *plistFilter = [NSPredicate predicateWithFormat:@"pathExtension='plist'"];
    NSArray *settingsPlistFiles = [fileinbundle filteredArrayUsingPredicate:plistFilter];
    for (NSURL *fileURL in settingsPlistFiles) {
        // extract preference specifiers
        NSArray *preferenceSpecifiers = [[NSDictionary dictionaryWithContentsOfURL:fileURL]objectForKey:kIASKPreferenceSpecifiers];
        // process each specifier in the current settings file
        for (NSDictionary *specifier in preferenceSpecifiers) {
            // get type of current specifier
            NSString *type = [specifier objectForKey:kIASKType];
            // need to check child pane specifier for additional file
            if ([type isEqualToString:kIASKPSChildPaneSpecifier]) {
                [preferenceFiles addObject:[specifier objectForKey:kIASKFile]];
            }else {
                // check if current specifier has a default value
                id defaultValue = [specifier objectForKey:kIASKDefaultValue];
                if (defaultValue) {
                    // get key from specifier and current stored preference value
                    NSString *key = [specifier objectForKey:kIASKKey];
                    id value = [defaults objectForKey:key];
                    // update preference value with default value if necessary
                    if (key && value == nil) {
                        [defaults setObject:defaultValue forKey:key];
                    }
                }
            }
        }
    }
    // synchronize stored preference values
    [defaults synchronize];
}
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment