15

I have an iOS application with a settings.bundle that handles various settings for my application with Switch toggle. I set default values in my root.plist file (using the DefaultValue property) to YES but any time the application launches on a device or the iOS simulator all values go NO. It worked well only on the first launch.

Settings Bundle PLIST

I am retrieving the defaults with this code (am I doing something wrong here?):

NSUserDefaults *localeDefaults = [NSUserDefaults standardUserDefaults];
BOOL ENWORDS = [localeDefaults boolForKey:@"localetime"];
Sam Spencer
  • 8,492
  • 12
  • 76
  • 133
iOS.Lover
  • 5,923
  • 21
  • 90
  • 162

5 Answers5

27

The Default Value is used by Settings.app for display purposes only. If you don't change the value in the settings app nothing is saved to NSUserDefaults.

You have to register the default values yourself. Use something like this in application:didFinishLaunchingWithOptions::

NSDictionary *userDefaultsDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithBool:YES], @"localetime",
                                      nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsDefaults];
Matthias Bauch
  • 89,811
  • 20
  • 225
  • 247
  • Nope ! nothing happened ! same problem ... Xcode 4.2 has lots of bug – iOS.Lover Feb 07 '12 at 18:33
  • 2
    +1 for best advice, but yet this is a workaround as the value set this way can be different from default value in plist. It's better to take the default value in plist as a value to be shown if nothing is set by user. – jackal Oct 13 '13 at 12:42
  • 1
    Thank you for saving me from banging my head against the desk for the next hour. – Jake Jan 19 '18 at 23:59
24

This blog post might help : http://greghaygood.com/2009/03/09/updating-nsuserdefaults-from-settingsbundle

tl;dr - until the user opens the settings page then the defaults aren't copied into your app. This is the expected behavior by Apple.

Personally, I think this is terrible. It means that you will have to set your defaults in code just in case the user starts your app without going to the settings page first (which will be true for about 99% of use cases!)

deanWombourne
  • 38,189
  • 13
  • 98
  • 110
  • tl;dr stands for 'too long; didn't read' - the second paragraph of my answer summarises the blog post in case you didn't read through it ;) Basically, you have to deal with the defaults in code as well as in the plist - the plist only takes effect if the user goes to the settings page first. – deanWombourne Feb 07 '12 at 20:15
  • 3
    Please see http://ijure.org/wp/archives/179 where it is explained that not all types have their default value set when a user goes into Settings, and in some cases the user has to actually choose a value other than the default before any value is saved for that item. In my case I noticed that Multi-value items were not set to the default. – ghr Oct 03 '13 at 03:49
17

The problem is the type of default Value must be boolean not string ;) delete this value and add a another default Value property again hope this helps

Mc.Lover
  • 4,813
  • 9
  • 46
  • 80
5
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //< Register Defaults
    NSString *settingsBundlePath = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    NSBundle *settingsBundle = [NSBundle bundleWithPath:settingsBundlePath];
    NSString *rootPlistPath = [settingsBundle pathForResource:@"Root" ofType:@"plist"];
    NSDictionary *settingsDict = [[NSDictionary alloc] initWithContentsOfFile:rootPlistPath];
    NSArray *settingsItems = [settingsDict objectForKey:@"PreferenceSpecifiers"];
    NSMutableDictionary *defaultDict = [NSMutableDictionary new];
    for (NSDictionary *itemDict in settingsItems) {
        if ([itemDict objectForKey:@"DefaultValue"]) {
            [defaultDict setObject:[itemDict objectForKey:@"DefaultValue"] forKey:[itemDict objectForKey:@"Key"]];
        }
    }
    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultDict];
    //< Following Code
}
mr.pppoe
  • 3,945
  • 1
  • 19
  • 23
  • This is good, if you don't have any variable settings you want to be able to change from iOS Settings. If you are, however, change the if statement to check if 'Key' doesn't exist and if it doesn't, set the default value object for it's key to `NSUserDefaults`. – mylogon Jan 03 '17 at 00:41
1

You can check whether the value has been set by getting objectForKey and checking whether it is nil.

   NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
   id dataExists = [userDefaults objectForKey:@"light_switch"];
   BOOL lightSwitch;
   if (dataExists != nil) {
      lightSwitch = [userDefaults boolForKey:@"light_switch"];
       NSLog(@"light_switch is %d", validateCertificates);
   } else {
      lightSwitch = YES; // default value
      NSLog(@"light_switch not set, default value is %d", validateCertificates);
   }
pzulw
  • 1,716
  • 15
  • 22
  • 2
    Bad, bad way of dealing with the problem. Use `-registerDefaults:` instead. See http://oleb.net/blog/2014/02/nsuserdefaults-handling-default-values/ – KPM Feb 13 '15 at 08:57