Store ON/OFF switch in NSUserDefaults? - ios

I have an app where I use NSUserDefaults to determine if it is the first time someone opens the app. If it is the first time, the app displays a tutorial page.
Now, I would like to change this so that if the user moves an ON/OFF switch to "ON", they will not see the tutorial when they start up the app. How do I store the user's selection of an ON/OFF switch in NSUserDefaults?

I did something like this with the following code:
Store it:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:YES forKey:#"the_key"];
[[NSUserDefaults standardUserDefaults] synchronize]; //Thanks Henri Normak
Retrieve it:
[[NSUserDefaults standardUserDefaults] objectForKey:#"the_key"]

Wrap it in an NSNumber numberWithBool:.
[defaults setValue:[NSNumber numberWithBool:mySwitch.on] forKey:#"mySwitchValue"];
// and get it out
BOOL savedSwitch = [[defaults valueForKey:#"mySwitchValue"] boolValue];

You need two bool keys to be saved in NSUserDefaults to get the what you want. e.g. firstTime is used check first time app launch, showTutorial is used to check/save the switch change
You can set your boolean by using:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"firstTime"];
and read it by using this code:
if([[NSUserDefaults standardUserDefaults] boolForKey:#"showTutorial"] || [[NSUserDefaults standardUserDefaults] boolForKey:#"firstTime"]) {
[self displayTutorial];
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"firstTime"];
}
else {
[self displayMainScreen];
}
Link the UISwitch on View from InterfaceBuilder to this action on valuechanged
-(IBAction)userSetOnOff:(id)sender
{
UISwitch *switchValue = sender;
if (switchValue.on){
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"showTutorial"];
}
else{
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"showTutorial"];
}
}

In one of my apps I check to see if NSUserDefaults has been used and if not set the one standard User Default variable.
-(id) init
{
standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *testInitState = [standardUserDefaults stringForKey:kInstallInit];
if (testInitState == nil)
{
#if(kStateModelDebug)
NSLog(#" State Model: First time initialized");
#endif
[self.standardUserDefaults setObject:#"true" forKey:kInstallInit];
[self.standardUserDefaults synchronize];
// Start the tutorials, init DB, etc
}
else
{
#if(kStateModelDebug)
NSLog(#" State Model has ALREADY been initialized");
#endif
// Read other state variables and/or init the startup processes
}
return self;
}
So far , up to ios 5.0 and the new 6.0, this has been a solution. Looking for comments on this solution.

One way is to simply persist a string with the switch status. If the user prefers the on position you'd store the string #"on". Else store the string #"off".
- (void) toggleUserPreference:(BOOL) preferOn {
NSString *newPreference = preferOn ? #"on" : #"off";
[[NSUserDefaults standardUserDefaults] setValue:newPreference
forKey:ONOFF_PREFERENCE_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}

Related

How to hide buttons, labels, etc for entire time iOS app is running, then show them again at start?

I'm coding an iOS app in Objective C. I want the terms and conditions to appear when a user opens the app. I'm going to have a "don't show these again" button, which is all figured out using NSUserDefaults. What I can't figure out is how to make the terms and conditions disappear if the user hits "agree" (termsPressed) but NOT "don't show these again" (neverAgainPressed). I can hide them using button.hidden, but then as soon as the user returns to the main screen of the app the terms and conditions appear again, overlaying the main screen just as they did when the app first launched.
I've tried setting an NSUserDefault when "agree" is pressed, then resetting it when -applicationWillTerminate is called, but it appears that applicationWillTerminate is not called reliably when the app closes if it's closed from the background, and hence the user would never see the terms again even if they hadn't hit "don't show these again". Here's my code:
- (void)viewDidLoad {
// Hide all the terms and conditions elements if either "neverAgain" or "termsPressed" is true
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL neverAgain = [defaults boolForKey:#"neverAgain"];
if (neverAgain == TRUE){
_terms.hidden=YES;
_hideTerms.hidden=YES;
_background.hidden=YES;
_dontShow.hidden=YES;
}
BOOL termsPressed = [defaults boolForKey:#"termsPressed"];
if (termsPressed == TRUE){
_terms.hidden=YES;
_hideTerms.hidden=YES;
_background.hidden=YES;
_dontShow.hidden=YES;
}
NSLog(#"View loaded. termsPressed = %i", termsPressed);
NSLog(#"View loaded. neverAgain = %i", neverAgain);
[super viewDidLoad];
}
- (IBAction)neverAgainPressed:(id)sender {
BOOL neverAgain = TRUE;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:neverAgain forKey:#"neverAgain"];
[defaults synchronize];
NSLog(#"Don't show terms again pressed, neverAgain set to TRUE");
}
- (IBAction)termsPressed:(id)sender {
_terms.hidden = YES;
_hideTerms.hidden = YES;
_background.hidden = YES;
_dontShow.hidden = YES;
BOOL termsPressed = TRUE;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:termsPressed forKey:#"termsPressed"];
[defaults synchronize];
NSLog(#"Terms accepted, termsPressed set to TRUE");
}
- (void)applicationWillTerminate:(UIApplication *)application {
BOOL termsPressed = FALSE;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:termsPressed forKey:#"termsPressed"];
[defaults synchronize];
NSLog(#"Application entering background, termsPressed reset to FALSE");
}
#end
If there was a method that was called every time an app quit, or a version of .hidden that lasted the whole time an app was running, I'd be all set. Let me know if you guys have any ideas.
If you want "don't show these again", why reset? You can show at first launch and after some time (30 days for example):
BOOL ranBefore = [[NSUserDefaults standardUserDefaults] boolForKey:#"kRanBefore"];
NSDate *lastDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"kLastCloseDate"];
NSTimeInterval timeDiff = [[NSDate date] timeIntervalSinceDate:lastDate];
int days = timeDiff / 86400;
if ((!ranBefore) || (days > 30)) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"kRanBefore"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:#"kLastCloseDate"];
... show something
}
or reser at
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}

How to Store data to NSUserDefaults in prepareForSeque

I am trying to do the following:
In settings scene change settings and when I press the "back" arrow, the changed data should be stored.
I assumed it should be done in the prepareForSeque method, as seen below:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSString* session_port = self.session_port.text;
NSString* session_address = self.session_address.text;
NSString* keep_alive_interval = self.session_keep_alive_interval.text;
[[NSUserDefaults standardUserDefaults] setObject:session_port forKey:#"sessionPort"];
[[NSUserDefaults standardUserDefaults] setObject:session_address forKey:#"sesssionAddress"];
[[NSUserDefaults standardUserDefaults] setObject:keep_alive_interval forKey:#"keepAliveInterval"];
}
However it does not seem to work as when I enter the settings window again, the data is still the standard data.
Can someone give me a hint in the right direction?
I load the data in the settings view like this:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.session_address.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"sesssionAddress"];
self.session_port.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"sessionPort"];
self.session_keep_alive_interval.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"keepAliveInterval"];
}
Instead for during the above in prepareForSeque it can be done in viewWillDisappear as presented below:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSString* session_port = self.session_port.text;
NSString* session_address = self.session_address.text;
NSString* keep_alive_interval = self.session_keep_alive_interval.text;
[[NSUserDefaults standardUserDefaults] setObject:session_port forKey:#"sessionPort"];
[[NSUserDefaults standardUserDefaults] setObject:session_address forKey:#"sesssionAddress"];
[[NSUserDefaults standardUserDefaults] setObject:keep_alive_interval forKey:#"keepAliveInterval"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
However this is not an optimal solution as NSUserDefaults are access every time you change the settings. one should use another means of propagating the change through out the application and then store the data when the applications is closed.

Removed NSUserDefaults

Here I can use NSUserDefaults, but I need to remove this NSUserDefaults.
In my app I'm using NSUserDefaults for getting locations one View to anotherView but here issue when I'm closed to the my app, and again I started still the locations are there, here I used for removing locations in AppDeligate
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults]removeObjectForKey:#"Location"];
}
But still locations is there.
How can I removed this?
Can you suggest me.
change your method
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults]removeObjectForKey:#"Location"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
into
- (void)applicationWillTerminate:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults]removeObjectForKey:#"Location"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
whenever you remove or add values in NSUserDefaults don't forget to call [[NSUserDefaults standardUserDefaults] synchronize];, if your fetching the values on that time no need to add [[NSUserDefaults standardUserDefaults] synchronize];

Unable to save NSUserDefaults values iOS

I want to open a ViewController only once when the app start for the very first time. Below is my code. The problem is when I am writing YES to NSUserdefaults , doing a synchronise , and then closing the app. in Xcode using simulator , the value is not updated to Yes.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"isFirstLaunch"])
{
// app already launched
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],#"isFirstLaunch", nil]];
[[NSUserDefaults standardUserDefaults]synchronize];
}
else
{
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],#"isFirstLaunch", nil]];
[[NSUserDefaults standardUserDefaults]synchronize];
}
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"isFirstLaunch"])
{
NSLog(#"first time");
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LASplashUserSettingViewController *splash = [storyboard instantiateViewControllerWithIdentifier:#"splash"];
[self.window.rootViewController presentViewController:splash animated:NO completion:nil];//
}
}
Why is NSUserDefaults not saving my values?
Have followed above and many other links. what am i missing here?
Thanks,
what am i missing here?
-registerDefaults: doesn't do what you think it does. Use -setBool:forKey: instead.
-registerDefaults: is used to ensure that values exist for certain keys in the defaults system. There's no need to call -synchronize after that method because the values in the registration domain are never saved. You probably meant to use that method to set up the default value YES for isFirstLaunch, but your code checks the value for the key before you register the default value! which defeats the purpose of the method. Proper use would be to call -registerDefaults: first, and then check the value associated with the key, and if the value is YES then call -setBool:forKey: to save the value NO.
A simpler option to detect the first launch would be to invert the question. Skip the -registerDefaults: call altogether and change the key to appHasRunPreviously. If no value is stored for a given key, -boolForKey: will return NO. If that happens, you know that this is the first time the app is running, and you should save YES for that key using -setBool:forKey:.
This is how you use NSUserDefaults in AppDelegate.m
+ (void)initialize
{
// Register defaults for first time
NSMutableDictionary *defs = [NSMutableDictionary dictionary];
[defs setObject:[NSNumber numberWithBool:YES] forKey:#"isFirstLaunch"];
[[NSUserDefaults standardUserDefaults] registerDefaults:defs];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults boolForKey:#"isFirstLaunch"])
{
// Do your stuff here
[defaults setBool:NO forKey:#"isFirstLaunch"];
[defaults synchronize];
}
}
Don't set isFirstLaunch back to YES in the else-condition if you only want the view to be shown once.
You can try this
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"AlreadyLaunched"];
[[NSUserDefaults standardUserDefaults]boolForKey:#"AlreadyLaunched"]

nsuserdefaults value getting replaced [duplicate]

This question already has answers here:
NSUserDefaults not working right
(3 answers)
Closed 9 years ago.
Inside the same viewcontroller class i am using two NSUserDefaults,one for saving UISwitch state and other one for DatePicker value.
Here is my code :
-(IBAction) switchValueChanged
{
NSString *value = #"ON";
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if (switch1.on)
{
value = #"OFF";
[userPreferences setObject:value forKey:#"stateOfSwitch"];
[switch1 setOn:YES animated:YES];
}
else
{
[userPreferences setObject:value forKey:#"stateOfSwitch"];
[switch1 setOn:NO animated:YES];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
}
- (IBAction)scheduleTime
{
NSDate *pickerTime=datePicker.date;
[[NSUserDefaults standardUserDefaults] setObject:pickerTime forKey:#"setPickerTime"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Problem is, only nsuserdefault for date picker is working,other one is not working.I think NSUserDefault value of DatePicker is replacing UISwitch's NsUserDefault value.Can anyone help me to solve this problem..
NSUserDefaults caches the information to avoid having to open the
user’s defaults database each time you need a default value. The
synchronize method, which is automatically invoked at periodic
intervals, keeps the in-memory cache in sync with a user’s defaults
database.
Add a [userPreferences synchronize]; invocation after the if/else block in the first function and try again.
try this code:
if (switch1.on)
{
value = #"OFF";
[[NSUserDefaults standardUserDefaults] setObject:value forKey:#"stateOfSwitch"];
[switch1 setOn:YES animated:YES];
}
else
{
[[NSUserDefaults standardUserDefaults] setObject:value forKey:#"stateOfSwitch"];
[switch1 setOn:NO animated:YES];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}

Resources