NSUserDefaults is not always saving my NSString data - iphone

I'm running into something a bit puzzling. I have some basic string data that I'm trying to save to the NSUserDefaults, like so:
NSString *state = #"finished";
[[NSUserDefaults standardUserDefaults] setObject:state forKey:#"downloadFinished"];
[[NSUserDefaults standardUserDefaults] synchronize];
When the app starts, one of the ways it makes decisions on which view to load is to check the value of this user setting:
NSString *savedState = [[NSUserDefaults standardUserDefaults] stringForKey:#"downloadFinished"]
if(savedState && [savedState length]) {
// Show view
}
Every once in a while, I've noticed that this value fails to load, even though I know for sure that this value was saved previously (or at least, the app tried to save it previously). When this happens, I'm getting a nil value back when I lookup the "downloadFinished" key from the user defaults.
Has anyone run into this before? Is there any knowledge out there on why this might happen? How likely is it that the save to the user's defaults cache and defaults database fails, and is there anyway to further prevent this from happening?
I'm going to try the solution mentioned in Why is NSUserDefaults not saving my values?, which forces another synchronize when the app enters the background, but I'm wondering if anyone has deeper knowledge on the matter.

I am guessing some data type issue here.
Can you try this instead, and see if you get something?
NSString *savedState = [[NSUserDefaults standardUserDefaults] objectForKey:#"downloadFinished"]
Notice objectForKey usage

Related

Strange iPhone SDK NSUserDefaults behaviour

I'm experiencing some strange NSUserDefaults behaviour. I save my data, then synchronize, then do a NSlog of the NSUserDefaults to make sure its saved. The data is shown as saved properly from the NSlog, but when I completely close the app (double click home button and kill the app) when it restarts the value has not changed. Whats even stranger is if I repeat the code several times by saving NSUserDefaults, killing the app, reloading the NSUserDefaults sometimes it gets saved properly and other times it does not.
I read this post Strange NSUserDefaults behavior but I am calling synchronize so I don't think thats my problem.
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:#"MyString" forKey:#"testString"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
Any help is greatly appreciated.
What really confuses me is if the NSLog of standardUserDefaults shows the data is saved why wouldn't it be after the app has been killed???
Thanks
UPDATE
Looks like the issue was with a mixup in mutable and immutable arrays i was saving to NSUserDefaults. I used mutablecopy when I was retrieving the data and seemed to solve the issue.
For getting the value you could use something like this
NSUserDEfaults *ud = [NSUserDefault standarUserDefaults];
[ud objectForKey=#"YourKey"];
If it returns nil it hasn't been saved.

Consistent NSUserDefaults saving

So in my app, I was saving some integer keys in NSUserDefaults,like around a minimum of 20.
Something like this but many:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setInteger:1 forKey:#"game1"];
[prefs setInteger:1 forKey:#"game2"];
[prefs setInteger:1 forKey:#"game3"];
So I was just wondering, should I call:
[[NSUserDefaults standardUserDefaults] synchronize];
Everytime I save?
Because sometimes I'm experiencing an inconsistency of the integer I'm saving and have been loading either with stopping, running the app in xCode or from the Home Button.
I have read a couple of articles on a site that stated:
In iOS4, your User Defaults may not get saved when pressing the home button. Manually calling [[NSUserDefaults standardUserDefaults] synchronize] in applicationDidEnterBackground: should ensure that your User Defaults is saved correctly.
Is this true and the same in iOS5? Or are there more accurate ways, shorter ways of saving integers. Thanks for the help.
Apple's documentation says this:
"Because this method is automatically invoked at periodic intervals, use this method only if you cannot wait for the automatic synchronization (for example, if your application is about to exit) or if you want to update the user defaults to what is on disk even though you have not made any changes."
So, depending on the urgency of the data you are settings, you may of may not need to call synchronize. Full documentation is here.
No you don't need to, when you call setInteger:forKey: on prefs, it automatically gets saved.

How to save variables after application shut down?

I want to save some integers after application shut down and restore them after application opening, what is the easiest way to do this?
You should store and load data from NSUserDefaults:
http://developer.apple.com/library/IOS/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// to store
[defaults setObject:[NSNumber numberWithInt:12345] forKey:#"myKey"];
[defaults synchronize];
// to load
NSNumber *aNumber = [defaults objectForKey:#"myKey"];
NSInteger anInt = [aNumber intValue];
Check out the NSUserDefaults documentation. You can set arbitrary key-value pairs there which (as long as you call the shared user defaults object’s -synchronize at some point before your app terminates) will persist between launches.
You can save them in the NSUserDefaults. This is mainly used for preferences.
[[NSUserDefaults standardUserDefaults] setObject:someInteger forKey:#"someIntegerKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
You can also save them to a Property List file if you have more data you'd like to store.
NSDictionary *someDictionary = [NSDictionary dictionaryWithObjectsAndKeys:someInt1, #"someIntKey1", someInt2, #"someIntKey2", nil];
[someDictionary writeToFile:somePath error:&error];
To save upon exiting the app place any code in
- (void)applicationWillTerminate:(UIApplication *)application
Look into using NSUserDefaults. This works like a dictionary that you can add key/value pairs to. You save the variables in your app delegate's applicationWillTerminate and applicationDidEnterBackground methods. You load the variables again in applicationDidFinishLoading.
The easiest way is to use NSUserDefaults. Your app delegate will get an -applicationWillTerminate: message when the app is about to shut down, and you can write your data to NSUserDefaults (or write it into your own file if the amount of data is large). Then, when your app starts up again, your app delegate will get an -applicationDidFinishLaunching, and you can read your data back again.
Serialize them and store them on memory. You have to do this before shut down and load when app is reopened

How to ship applications with some preferences set to a set value

I have one preference in my application that I want my app to be "shipped" with, how do I do this?
Thanks in advance.
Create an NSDictionary then use
[myDict setObject:#"defaultvalue" forKey:#"mykey"];
for each of your default values. Then use
[[NSUserDefaults standardUserDefaults] registerDefaults:myDict];
It is safe to always do this on startup as it won't overwrite settings. When you go to read the value for your settings via
[[NSUserDefaults standardUserDefaults] objectForKey:#"mykey"];
you will get your default value, or the value that you subsequently set.
Store this preference in your app bundle as part of some set of defaults. When your app launches for the first time (an no saved preferences exist) save this value to NSUserDefaults, the documents directory, or where ever you store your app's preferences.
If there is nothing set in the defaults for a given key, set something. You can do this check whenever your app loads, at any time after the first run, you'll always have an object for your #"MySpecialPref" key.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"MySpecialPref"]) {
[defaults setBool:YES forKey:#"MySpecialPref"];
}
You could also ship it with a default SQLite database that contains custom values, and use them in your app

Why won't my NSUserDefaults load?

So I have an iphone app that presents a modal view when it starts if the user has not registered. Once they register, it saves a user ID into NSUserDefaults. When the app starts at a later time, it needs to load this user id in the appdelegate file.
//Registration.m
NSUserDefaults *savedUID = [NSUserDefaults standardUserDefaults];
[savedUID setObject:UID forKey:#"user_id"];
//AuctionTracAppDelegate.m
NSUserDefaults *savedID = [NSUserDefaults standardUserDefaults];
NSString *uidString = [savedID stringForKey:#"user_id"];
My problem is that when I try to load this value at a separate execution, the object I saved is always null. I know for a fact that it is saving the string object correctly. Also, this weird behavior JUST surfaced. This exact code was working earlier, then after working on a totally unrelated file, this code fails. I'm clueless as to what happened. Any hints?
I believe that you need to call the synchronize method.