How to store settings on iPhone immediately? - iphone

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.

Related

iOS: override NSLocale language

If you have a localized version of your app in several languages but if the user is not using any of the languages the app is localize.
How to set a default language? Or what will be the best practice to define a default language in this case?
Here are the scenarios I was trying to tackle:
The application has be localize in en/fr/es but if language locale is not en/fr/es how you define a default?
In case the the language locale is either one of this en/fr/es and the user whants to use a different language define on there NSUserDefaults. Let's say is using english as NSUserDefaults but wants to use the fr localized version of the aplication. There is a way to overwrite the language on NSUserDefaults ?
write the NSUserDefaults before the apps start
question1 : you can set your prefer order as below.
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"de", #"en", #"fr", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
Question2: force to use fr
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"de", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
I'm finding this no longer works in iOS 9 (and probably 10). We have several targets in our code base. For a couple of them I always want it to come up in English even though localized strings may be present in the bundle.
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"en", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
I have added the above code in main(). The first time the app runs it comes up in the user's chosen language. On subsequent runs it will come up in English as desired.
Can anyone confirm this doesn't work in iOS 9 and suggest an alternative? I'd rather not delete the other lproj entries if I don't have to.

How to implement instruction view for iPhone app

I have 2 pages that I want to show as instructions the first time the app is run. How would I accomplish this?
You can utilize NSUserDefaults for something like this.
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"didLoad"]) {
//Show your instructions
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"didLoad"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
What this does is, check if the didLoad bool is FALSE (Which will be on first Load), if it is you show your instructions and set the BOOL to YES for the next Launch. You can put this in your viewDidLoad method.

iOS able to read plist file on simulator but not on device

Previously I read posts with same problem but my question persists. My app needs to read firstly a plist file to get some parameters and, when loaded on device, is unable to read default settings plist (working on simulator). One solution should be copy that plist into documents directory, but only this one? Is device unable to read user defaults set in plist? if I copy it to docs directory, will device be able to associate keys for plist if has another location? I need to read user defaults before executing any function. Thank you.
-(void)loadSettings
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.userID = [[NSUserDefaults standardUserDefaults] stringForKey:#"userID"];
self.nom2 = [[NSUserDefaults standardUserDefaults] stringForKey:#"t2"];
self.nom3 = [[NSUserDefaults standardUserDefaults] stringForKey:#"t3"];
self.nom4 = [[NSUserDefaults standardUserDefaults] stringForKey:#"t4"];
self.currentGlobal = [[NSUserDefaults standardUserDefaults] stringForKey:#"versionApp"];
NSLog(#"Version App = %#", currentGlobal);
self.colorTab = [[NSUserDefaults standardUserDefaults] stringForKey:#"color"];
firstBoot = [[NSUserDefaults standardUserDefaults] boolForKey:#"firstBoot"];
[defaults synchronize];
}
It sounds like you just want to set some initial values in user defaults so your app can read them in. If that is the case then you'll simply want to use the registerDefaults: method of NSUserDefaults. Example:
[[NSUserDefaults standardUserDefaults] registerDefaults:
[NSDictionary dictionaryWithObject: [NSNumber numberWithBool:YES]
forKey: #"firstBoot"]];
The beauty of NSUserDefaults is you never have to mess with pList stuff or the iOS filesystem.
You do no need to copy the plist for the standardUserDefaults to the documents directory. You should let iOS create this file on its own and not include it with your app. If you need to set defaults, then you should use the registerDefaults: method on the standardUserDefaults instance to do so by passing in a dictionary of key-value pairs.
Have you looked at using NSUserDefaults?
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
It automatically does what you are describing and you don't need to manage files. It's a simple API that you can read and write settings to and iOS takes care of storage for you.

Detecting the initial launch of an app using NSUserDefaults

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.

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