views:

187

answers:

3

I made some preferences in my Settings.bundle that show up fine in the Settings app. However my settings always return nil when I read them back. I know I need to set a default value on first startup. But even after that and going to the settings menu (which should also set the default values) - when I read them back I always get nil.

Even when I set the default and read it back immediately I get nil!

  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"YES" forKey:@"displaySunTimes"];
  [defaults registerDefaults:appDefaults];
  [defaults synchronize];

  bool test =[defaults boolForKey:@"displaySunTimes"];
  NSLog(@" Value %@", test);

Here's the beginning of my root.plist

<dict>
    <key>StringsTable</key>
    <string>Root</string>
    <key>PreferenceSpecifiers</key>
    <array>
            <dict>
                    <key>Type</key>
                    <string>PSGroupSpecifier</string>
                    <key>Title</key>
                    <string>Display Sunrise / Sunset times for your location.</string>
            </dict>
            <dict>
                    <key>Type</key>
                    <string>PSToggleSwitchSpecifier</string>
                    <key>Title</key>
                    <string>Sunrise / Sunset</string>
                    <key>Key</key>
                    <string>displaySunTimes</string>
                    <key>DefaultValue</key>
                    <true/>
                    <key>TrueValue</key>
                    <string>YES</string>
                    <key>FalseValue</key>
                    <string>NO</string>
            </dict>
A: 
  • A little odd to be using a String to represent a bool value. Try [NSNumber numberWithBOOL: YES] instead. As others pointed out (and I'd forgotten), use the boolForKey: and setBool:forKey: APIs on NSUserDefaults.

  • When I've run into something like this it is because I somehow managed to push the wrong defaults value into the defaults database. Are you sure you don't have a default value from a previous run sticking around?

Registration defaults are the default value to use when a value has not been previously set.


Unless the app and all data is being deleted between each run, then this still sounds exactly like you have a default value already set and the registration default isn't overriding it (correct behavior).

Try manually setting the default to some other value and synchronizing.

Note also that synchronize is completely orthogonal to registration defaults.

bbum
Still didn't with that bool. Am sure I don't have anything in preferences, I deleted the app and reinstalled and tried again. My root.plist is above.
mm1
A: 

If you want to store a BOOL then use:

[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"displaySunTimes"];

In order to retrieve it from defaults:

[[NSUserDefaults standardUserDefaults] boolForKey:@"displaySunTimes"];

EDIT:
Change the NSLog(@" Value %@", test); to NSLog(@" Value %i", test); (BOOL is not an object).
In addition, use BOOL instead of bool.

Michael Kessler
Still doesn't work :( how strange. It's as if the "dislaySunTimes" key isn't getting set right.
mm1
I have edited my answer. See if it solves your problem...
Michael Kessler
Prefer C99's bool. BOOL is a signed char.
tc.
Got it, thanks!
mm1
+1  A: 

It helps if you understand the difference between @"YES", [NSNumber numberWithBOOL:YES], and YES.

In this case, it's returning "NO" ((BOOL)0), not "nil" ((id)0). Use objectForKey: if you want to know if something is stored at all. In this case, you are storing the NSString @"YES" and trying to read it as a bool; I refer you to the docs for boolForKey:

If a boolean value is associated with defaultName in the user defaults, that value is returned. Otherwise, NO is returned.

A string is not a boolean, so @"YES" becomes NO. Try something like this:

NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:[NSNumber numberWithBOOL:YES] forKey:@"displaySunTimes"];
tc.