Detecting the initial launch of an app using NSUserDefaults - iphone

In reference to the following question: iPhone: How do I detect when an app is launched for the first time?
When I looked up NSUserDefaults apple reference, it said that registerDefaults does not store the data onto the disk. In the above question, the app registers the value firstLaunch to YES upon each launch. So each time the app is launched, firstLaunch is overwritten to YES and so the app will always think that this is the app's initial launch.
Am I right on this?
EDIT:
After doing what the tutorial above says, it doesn't always work anyway. I keep relaunching from Xcode and it keep printing out 1 bool value as in its the first launch.

registerDefaults: doesn't overwrite what is already in the defaults, but it sets defaults-for-the-defaults. So if a default is missing it uses a default-default. Confusing, isn't it?
If you've never written a value under the key FirstLaunch, then boolForKey:#"FirstLaunch" will use the value from registerDefaults:. However, if you did previously do setBool:NO forKey:#"FirstLaunch" and later ask for it again with boolForKey: then the value from registerDefaults: is not used.

registerDefaults: doesn't overwrite existing values, it only initializes values that aren't set to any value yet.

Try something like this in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
if ([[[NSUserDefaults standardUserDefaults] valueForKey:#"firstRun"] intValue]==0) {
//do the stuff required at first launch
//after stuff done
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:1] forKey:#"firstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}

NO first it will be nil then you set it to yes and before setting it to yes check if it's already set to yes or not. So first time userDefaults will return nil if you get something for a key. like
[[NSUserDefaults standardUserDefaults] valueForKey:#"FirstLaunch"];
will return nil on first launch of application.

Related

NSUserDefaults not saving in iOS 7

I'm having this issue with NSUserDefaults. It is saving the defaults until I kill the app in the background then when I return all the defaults are gone. They are also gone every time a build a new version onto my device. But again, they are there within app so long as I don't kill it in the background. It's working fine in iOS 6. Thoughts?
Take your value in string(or any other as per your requirement) and save the string in user defaults
NSUserDefaults *userdefault=[NSUserDefaults standardUserDefaults];
NSString *str=[NSString stringWithFormat:#"%#",[dicUser objectForKey:#"device_token"]];
[userdefault setObject:str forKey:#"YOURKEY"];
Since you haven't your code, so i am giving example which is perfectly working for me on iOS 7, give it a try. Hopefully works for you too.
For saving boolean value
bool flag = YES;
[[NSUserDefaults standardUserDefaults] setBool:flag forKey:#"flag"];
For retrieving boolean value
bool flag = [[NSUserDefaults standardUserDefaults] boolForKey:#"flag"];
make sure few things like you have declared the userDefaults before using it and if you've taken that in you AppDelegate file then here is a sample code how i am saving values and it works fine so try it this way
APP_DELEGATE.userDefaults = [NSUserDefaults standardUserDefaults];
[APP_DELEGATE.userDefaults setObject:#"unChecked" forKey:#"CheckMark"];
[APP_DELEGATE.userDefaults synchronize];
here APP_DELEGATE is declared like this in my AppDelegate.h file
#define APP_DELEGATE ((AppDelegate*)[[UIApplication sharedApplication] delegate])
hope it helps!

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 store settings on iPhone immediately?

Is it possible to store settings on the iPhone immediately? The apps on iOS 4+ don't close on exit, and if I press 'Stop process' in Xcode settings are not saved? How to save them?
- (void)compLoad {
compTotal = [[NSUserDefaults standardUserDefaults] integerForKey: #"compTotal"];
compCount = [[NSUserDefaults standardUserDefaults] integerForKey: #"compCount"];
compShow = [[NSUserDefaults standardUserDefaults] boolForKey: #"compShow"];
}
- (void)compSave {
[[NSUserDefaults standardUserDefaults] setInteger: compTotal forKey: #"compTotal"];
[[NSUserDefaults standardUserDefaults] setInteger: compCount forKey: #"compCount"];
[[NSUserDefaults standardUserDefaults] setBool: compShow forKey: #"compShow"];
}
[[NSUserDefaults standardUserDefaults] synchronize];
synchronize - 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.
According to the documentation, the following call will persist any outstanding modifications. To check if this has been successful, check the return value of this call. A value of YES indicates success.
[[NSUserDefaults standardUserDefaults] synchronize];
Call your compSave in your AppDelegate
- (void)applicationWillResignActive:(UIApplication *)application
{
// Call your compSave here to force saving before app is going to the background
}
also
- (void)compSave
{
[[NSUserDefaults standardUserDefaults] setInteger: compTotal forKey: #"compTotal"];
[[NSUserDefaults standardUserDefaults] setInteger: compCount forKey: #"compCount"];
[[NSUserDefaults standardUserDefaults] setBool: compShow forKey: #"compShow"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Simply call [[NSUserDefaults standardUserDefaults] synchronize];. But usually you do not need to that: iOS will save once your app goes into background and also on a few other occasions. Calling synchronize too often is a considered to be a Bad Thing(tm).
Try using the synchronize method.
Update: you should consider registering your defaults, like it suggests in the Preferences and Settings Programming Guide:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Register the preference defaults early.
NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:#"CacheDataAgressively"];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
// Other initialization...
}
Also, from this guide ("Synchronizing and Detecting Preference Changes"), regarding syncing:
To detect when changes to a preference value occur, apps can also register for the notification NSUserDefaultsDidChangeNotification. The shared NSUserDefaults object sends this notification to your app whenever it detects a change to a preference located in one of the persistent domains. You can use this notification to respond to changes that might impact your user interface. For example, you could use it to detect changes to the user’s preferred language and update your app content appropriately.
Pretty sure you still need to use synchronize if you want to re-read settings directly.

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