NSUserDefaults not saving
Asked Answered
T

6

7

I am having a problem in my sprite kit app where my NSUserDefaults variable is not working. In createSceneContents (which I know is being called)

if (![defaults objectForKey:@"obj"]) {
    difficultyLabel.text = @"Difficulty: Easy";
    [defaults setObject:@"Easy" forKey:@"obj"];
} else {
    difficultyLabel.text = [NSString stringWithFormat:@"Difficulty: %@", [defaults objectForKey:@"diff"]];
}

and then when you click on the SKLabelNode to change the difficulty and this code is being called

if ([label.text isEqualToString:@"Difficulty: Easy"]) {
            label.text = @"Difficulty: Hard";
            [defaults setObject:@"Hard" forKey:@"obj"];
            NSLog(@"%@",[defaults objectForKey:@"obj"]);

        } else {
            label.text = @"Difficulty: Easy";
            [defaults setObject:@"Easy" forKey:@"obj"];
            NSLog(@"%@",[defaults objectForKey:@"obj"]);

but when I stop the program and run it again, it always just says Difficulty: Easy. Any suggestions?

Tabloid answered 19/2, 2014 at 0:9 Comment(0)
I
27

As rmaddy's answer explains, NSUserDefaults won't immediately write data to long-term storage.

The values are saved in temporary memory when you call setObject:forKey:, so if you ever try to call objectForKey: after setObject:forKey:, it will return the value in memory if it exists, and if not, it goes to look for what's been saved to long-term storage.

In the background, the device will eventually save these values to permanent storage. It's something the OS handles, but in normal operation of your app, it shouldn't be necessary to immediately store these values to permanent storage most of the time, so let the OS do this at times when its been optimized to do so (I imagine the OS probably synchs every app's user defaults at once on some regular schedule, and as much as possible, tries to do this when the processor is idle probably).

But with that said, as rmaddy explains, if you've got something that crucially needs to be saved to the permanent storage immediately, you can always call synchronize. Keep in mind though... as long as your app isn't killed while in debug mode, the values you've set to be stored in user defaults will be stored.

But for your own sake, if you want to be absolutely certain, you can put it a call to synchronize in applicationDidEnterBackground as rmaddy suggests. Keep in mind though, this method isn't called if you kill the app.

Ionium answered 19/2, 2014 at 0:30 Comment(1)
The comment about debug mode cant be emphasized enough. I was sitting here trying to figure out why my default value was not being set correctly because I wasn't aware of the caching going on.Gareth
M
14

When you say you "stop the program", what do you mean? Are you running in the debugger and killing the app and rerunning it again? NSUserDefaults doesn't persist your changes immediately. Either call [defaults synchronize] after writing important data or at least add such a call to your app delegate's applicationDidEnterBackground method. And then be sure you put your app in the background before killing it to ensure the data is written first.

Multifoliate answered 19/2, 2014 at 0:16 Comment(1)
thanks. With the [defaults synchronize] its working fineTabloid
C
2

I found another reason why NSUserDefaults not saving,following code can make value in NSUserDefaults not saving:

NSUserDefaults *def= [[NSUserDefaults standardUserDefaults] init];
...
NSUserDefaults *def= [[NSUserDefaults standardUserDefaults] initWithSuiteName:@"123"];

You can search NSUserDefaults in your project to catch those init twice bug.

Cabriole answered 20/9, 2016 at 4:30 Comment(1)
Thanks, that's exactly my case!Garrison
T
1

To store:

NSString * str = @"name123";
NSUserDefaults *def=[NSUserDefaults standardUserDefaults];
[def setObject:str forKey:@"Key"];
[def synchronize];
NSLog(@"str = = %@",str);

To Retrieve:

NSUserDefaults *def=[NSUserDefaults standardUserDefaults];
NSString *str2 = [def valueForKey:@"Key"];
NSLog(@" Saved str  = = %@",str2);
Turnbuckle answered 24/2, 2014 at 8:2 Comment(0)
D
0

I had this issue where it was working previously but then wasn't. I couldn't figure it out.

It turned out restarting my mac fixed it. There must be some issue with the prefsd daemon that runs in the background that can cause this I'm guessing

Derick answered 31/5, 2021 at 10:2 Comment(0)
D
0

Old question, but in The docs for NSUserDefaults, for synchronize, Apple says: "this method is unnecessary and shouldn't be used."

Diagnostics answered 25/4, 2023 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.