NSUserDefaults cannot stop application launch / startup

EDIT: Code updated to reflect Paul.s.

Been browsing SO last week and still can't get my app to save settings changes from app to shutdown / restart app in Sim and on device.

Trying to use NSMutableDictionary from Singleton, but I don't think this is the problem.

a) Set initial default values ​​for the application using registerDefaults in the AppDelegate applicationDidFinishLaunchingWithOptions:

AppManager *global = [AppManager sharedInstance];

// set up the defaults.
global.gWantFoo = YES;    // This is a BOOL which relates to a UISwitch

// #define kWantFoo @"gWantFoo"
global.globalSettingsDict = [[NSMutableDictionary alloc] 
                               [NSNumber numberWithBool:global.gWantFoo], kWantFoo, nil];

global.globalSettings = [NSUserDefaults standardUserDefaults];
[global.globalSettings registerDefaults:global.globalSettingsDict];
[global.globalSettings synchronize];


b) In ConfigView, where I can set a switch, I have a selector doing the following when changing a switch.

self.global.gWantFoo = NOT(self.global.gWantFoo);   // #define NOT(a)  !(a)
[self.global.globalSettings setBool:self.global.gWantFoo forKey:kWantFoo];
[self.global.globalSettings synchronize];


c) I have a sync on applicationDidEnterBackground and friends, and although the switch value persists for the lifetime of the application, after a reboot, gWantFoo is overwritten by default "YES".

Any advice is appreciated. I am on the verge of defending my ailing macbook pro with a barrage of curses by following him closely. Ok, I settled down for this edit. I feel myself gently shaking my macbook pro to demonstrate that I am less than happy with NSUserDefaults :-)




source to share

2 answers

So from start to finish this is what you have to do / what has to happen

In application:didFinishLaunchingWithOptions:

one of the first things you do - it is the default value, such as:

NSDictionary *defaultsDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:NO] , PSWantFoo, nil];

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults registerDefaults:defaultsDefaults];


Note: PSWantFoo

defined as NSString * const PSWantFoo = @"PSWantFoo";

, so I don't have string literals littered all over the place.

At this point, if the application has never started NSLog(@"%d", [defaults boolForKey:PSWantFoo]);

, it will print 0


Now when I want to set a value, I use something like:

[defaults setBool:YES forKey:PSWantFoo];
[defaults synchronize];


Now when I run NSLog(@"%d", [defaults boolForKey:PSWantFoo]);

it will print 1


As for the persistence at this point, since I actually set the value, then a plc layer is created for me

<path to app>/Library/Preferences/<bundle identifier>.plist


If you check this file, you will see something like

<?xml version="1.0" encoding="UTF-8"?>
<DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">


Now from this point this value will be read in contrast to the one registered in registerDefaults:


Why did you enter this code in this order?

// set up the defaults.
global.gWantFoo = YES;    // This is a BOOL which relates to a UISwitch


Why not do it the other way around?

Register defaults with default YES;

NSDictionary *defaultsDefaults = [[NSDictionary alloc] initWithObjectsAndKeys: 
                                   [NSNumber numberWithBool:YES], kWantFoo, nil];

[defaults registerDefaults:defaultsDefaults];


and then after that you get the setting

global.gWantFoo = [defaults boolForKey:kWantFoo];


So, if the app hasn't set a preference yet, the answer will be YES

, otherwise it will be what the app previously set it to.



You must set the @ "gSettingsAreSet" flag after saving the defaults

[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"gSettingsAreSet"];
[[NSUserDefaults standardUserDefaults] synchronize];




All Articles