Saving and Loading settings by NSUserDefault on UIswitches Xcode - iphone

I have a settings view where i have provided the option for users to change their settings.
Settings view have a table view having 2 UISwitches. I need help with NSUserdefaults method for saving states, and how I can write the code to load my values.
Here is my code so far
In `cellForRowAtIndexPath` method:
[cell.switchButton addTarget:self action:#selector(switchButtonTapped:) forControlEvents:UIControlEventValueChanged];
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"myBool"];
BOOL hBool = [[ NSUserDefaults standardUserDefaults] boolForKey:#"myBool"];
NSLog(#"tag %i", tappedSwitch.tag);
if (cell.switchButton.tag == 0) {
[cell.switchButton setOn:hBool];
}
return cell;
}
- (void) switchButtonTapped: (id) sender {
tappedSwitch = (UISwitch *) sender;
switch (tappedSwitch.tag) {
case 0:
passcodeSwitchIsOn = tappedSwitch.isOn;
if (passcodeSwitchIsOn) {
GCPINViewController *PIN = [[GCPINViewController alloc]
initWithNibName:nil
bundle:nil
mode:GCPINViewControllerModeCreate];
PIN.messageText = #"Enter a passcode";
PIN.errorText = #"The passcodes do not match";
PIN.title = #"Set Passcode";
PIN.verifyBlock = ^(NSString *code) {
NSLog(#"setting code: %#", code);
code = saveString;
return YES;
};
[PIN presentFromViewController:self animated:YES];
[PIN release];
// method of saving
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:passcodeSwitchIsOn forKey:#"myBool"];
[defaults synchronize];
}
break;
case 1:
bluetoothSwitchIsOn = tappedSwitch.isOn;
if (bluetoothSwitchIsOn) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Bluetooth Switch" message:#"Bluetooth Switch is ON" delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
default:
break;
}
[settingsTable reloadData];
}

Create a reference to your user defaults:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
Set a value:
[defaults setBool:1 forKey:#"bluetooth"];
You can set this back to 0 when bluetooth is off:
[defaults setBool:0 forKey:#"bluetooth"];
The user default is identified by the string of your choice. In this case: #"bluetooth". The value for the default will be nil until you create it and set it to something else.
So you can say:
if (!bluetooth) // bluetooth is off
else // bluetooth is on
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html

This can be used for handling your issue.
IBOutlet UISwitch * swi_yourswitch;
#property(nonatomic,retain) UISwitch * swi_yourswitch;
implimentation
#synthesise swi_yourswitch;
- (void) switchButtonTapped: (id) sender {
UISwitch * switchObj = (UISwitch*)sender;
if(switchObj == self.swi_yourswitch){
if (self.swi_yourswitch.on){
NSLog(#"On");
}
else{
NSLog(#"Off");
[self.swi_yourswitch setOn:0];
}
}
To store value
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"mybool"];
[[NSUserDefaults standardUserDefaults] synchronize];
To get stored value
[NSUserDefaults standardUserDefaults] valueForKey:#"mybool"]

Related

How to save UISwitch state on plist file?

i am trying to save the state of UISwitch .If the UISwitch state is "ON" and when the user quits the app and starts it again ..the app should show the previous state and if the user plans to change the state of UISwitch to "OFF"..he should get a message saying previously he had "ON" state and change to state to "OFF"
if you guys help me out that would be great .Thanks
-(IBAction)notification:(id)sender
{
if (sender == notifyMe)
{
if(notifyMe.isOn == YES)
{
toggle = YES;
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:notifyMe.on forKey:#"switchValueKey"];
[defaults synchronize];
NSLog(#"Notification is ON");
}
else
{
toggle = NO;
NSLog(#"Notification is OFF");
}
}
if ([cellDelegate respondsToSelector:#selector(notificationReqd:)])
{
[cellDelegate notificationReqd:self];
}
}
Change your button action method like:
-(IBAction)notification:(id)sender
{
if (sender == notifyMe)
{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
BOOL previousState = [defaults boolForKey:#"switchValueKey"];
if(notifyMe.isOn == YES)
{
toggle = YES;
NSLog(#"Notification is ON");
}
else
{
toggle = NO;
NSLog(#"Notification is OFF");
}
[defaults setBool:toggle forKey:#"switchValueKey"];
[defaults synchronize];
//You can show the message here
NSLog(#"Previous state was %d",previousState);
}
if ([cellDelegate respondsToSelector:#selector(notificationReqd:)])
{
[cellDelegate notificationReqd:self];
}
}
When you want to get the stored data you can use:
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
BOOL previousState = [defaults boolForKey:#"switchValueKey"];

How to save value in the plist and acces the plist?

I have a UITableView with a UISwitch button in it. I want that when I run my application default value of the UISwitch button should be ON. If I toggle the switch button from on to off the value in the plist should change to OFF. If I quit the app and then I again run my app the value should again default to ON in the plist.
I have tried using NSUserDefaults, it works i.e when I change the value from ON to OFF the value in NSUserDefaults also changes. But when the app is run again the default value is not set to ON.
- (void)viewDidLoad {
[super viewDidLoad];
settings = [[NSMutableArray alloc]initWithObjects:#"Clock",#"Time Format",#"Weather",#"Degrees",nil];
switchControl = [[UISwitch alloc]initWithFrame:CGRectMake(205, 110, 20, 15) ];
[self.switchControl addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:switchControl];
NSString *viewdid = #"ON";
userdefaults = [NSUserDefaults standardUserDefaults];
[userdefaults setObject:viewdid forKey:#"stateOfSwitch"];
}
- (void)viewWillAppear:(BOOL)animated {
NSString *_value= [[NSUserDefaults standardUserDefaults] stringForKey:#"stateOfSwitch"];
if([_value compare:#"ON"] == NSOrderedSame){
[switchControl setOn:YES animated:YES];
}
else {
[switchControl setOn:NO animated:YES];
}
[super viewWillAppear:animated];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 4;
}
-(void)switchChanged:(id)sender
{
app= (StopSnoozeAppDelegate*)[[UIApplication sharedApplication]delegate];
NSString *value = #"ON";
userdefaults = [NSUserDefaults standardUserDefaults];
if(!switchControl.on){
value = #"OFF";
[userdefaults setObject:value forKey:#"stateOfSwitch"];
}
[userdefaults setObject:value forKey:#"stateOfSwitch"];
[userdefaults synchronize];
}
//this is my second class where i am accessing my userdefaults key and depending on that hiding the views
- (void) viewWillAppear:(BOOL)animated
{
NSString *_value= [[NSUserDefaults standardUserDefaults] stringForKey:#"stateOfSwitch"];
if([_value compare:#"ON"] == NSOrderedSame){
newview.hidden = NO;
newnewview.hidden =NO;
firstview.hidden = NO;
secondview.hidden = NO;
thirdview.hidden = NO;
}
else if([_value compare:#"OFF"] == NSOrderedSame) {
newview.hidden = YES;
newnewview.hidden= YES;
firstview.hidden = YES;
secondview.hidden = YES;
thirdview.hidden = YES;
}
}
In appDelegate did finish loading write below statements
[[NSUserDefaults standardUserDefaults] setObject:#"OFF" forKey:#"stateOfSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
May be you have not dump new values to plist?
Try to call [[NSUserDefaults standardUserDefaults] synchronize]; after setting new value to NSUserDefaults.
Either do
// set when launching the app
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[[NSUserDefaults standardUserDefaults] setObject:#"OFF" forKey:#"stateOfSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
or
// set when terminating
- (void)applicationWillTerminate:(UIApplication *)application
[[NSUserDefaults standardUserDefaults] setObject:#"OFF" forKey:#"stateOfSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Furthermore, you should test your NSString using isEqualToString: as compare: may lead to false positives (e.g. if one of the strings is nil).
You shouldn't store a string, which has the potential for parsing bugs, when NSUserDefaults is perfectly capable of storing BOOLs directly.
Just store it like this:
#define StateOfSwitch #"StateOfSwitch"
-(void)switchChanged:(id)sender
{
[[NSUserDefaults standardUserDefaults] setBool:switchControl.on forKey:StateOfSwitch];
[[NSUserDefaults standardUserDefaults] synchronize];
}
and then later, load the value like this:
switchControl.on = [[NSUserDefaults standardUserDefaults] boolForKey:StateOfSwitch];
(Note it's a good idea to never use string keys directly, it's better to #define them to prevent typo errors. Plus you get command + click to jump to definition, autocompletion, etc.)

iPhone: preserve NSUserDefaults values when application is killed

I am trying to implement "Add to Favorites" functionality using NSUserDefaults. So far I have written following code.
- (void)favouriteButtonClicked:(id)sender
{
favselected = !favselected; // favselected is BOOL property
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString* viewname = #"custom";
if(favselected) {
[favButton setBackgroundImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateNormal];
[appDelegate addTOFavourites:self.ViewID viewType:self.ViewType];
} else {
[favButton setBackgroundImage:[UIImage imageNamed:#"unselected.png"] forState:UIControlStateNormal];
[appDelegate removeFromFavourites:self.ViewID viewType:self.ViewType];
}
}
It is working fine as long as my application is running but when I killed my application, I am losing all my stored values so when next time view loaded, in viewload isAddedToFavorites method returns false. Is there anyway to preserve my values? Am I missing something?
if([appDelegate isAddedToFavorites:self.ViewID]) {
[favButton setBackgroundImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateNormal];
favselected = YES;
} else {
[favButton setBackgroundImage:[UIImage imageNamed:#"unselected.png"] forState:UIControlStateNormal];
favselected = NO;
}
Edit:
I tried using NSMutableDictionary as I have to add multiple key-values but following method always display Count=0 even after adding object to dictionary. Any help would be really appreciated. Thank you.
-(BOOL)isAddedToFavorites:(NSString*)viewID {
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *favourites = [[standardUserDefaults objectForKey:kFavouriteItemsKey] mutableCopy];
if(favourites && [[favourites objectForKey:kFavouriteItemsKey] objectForKey:viewID])
return YES;
return NO;
}
-(void)addToFavourites:(NSString*)viewID viewType:(NSString*)viewType {
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *dict = [[standardUserDefaults objectForKey:kFavouriteItemsKey] mutableCopy];
if(standardUserDefaults) {
if(![dict objectForKey:viewID])
[dict setObject:viewType forKey:viewID]; // It is coming here but still count zero!
NSLog(#"count = %d", [dict count]);
[standardUserDefaults setObject:dict forKey:kFavouriteItemsKey]; // Always dict remains null with 0 objects in it
[standardUserDefaults synchronize];
[dict release];
}
}
-(void)removeFromFavourites:(NSString*)viewID viewType:(NSString*)viewType {
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *dict = [[standardUserDefaults objectForKey:kFavouriteItemsKey] mutableCopy];
if(standardUserDefaults) {
if ([dict objectForKey:viewID])
[dict removeObjectForKey:viewID];
[standardUserDefaults setObject:dict forKey:kFavouriteItemsKey];
[standardUserDefaults synchronize];
[dict release];
}
}
Thanks.
NSUserDefaults is actually used to store values permanently, in fact if you create any Settings for your program they will be saved as NSUserDefaults.
I think the problem is that you are not saving it with the same key you are retrieving. Try saving like this:
//To save
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:appDefaults forKey:kFavouriteItemsKey];
[[NSUserDefaults standardUserDefaults] synchronize];
//To retrieve
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *favourites = [[standardUserDefaults objectForKey:kFavouriteItemsKey] mutableCopy];
For the dictionary try:
NSDictionary *myDictionary= [[NSUserDefaults standardUserDefaults] objectForKey:kFavouriteItemsKey];
// Create a mutable dictionary to replace the old immutable dictionary
NSMutableDictionary *myMutableDictionary= [NSMutableDictionary dictionaryWithCapacity:[myDictionary count]+1];
// transfer the old dictionary into the new dictionary
[myMutableDictionaryaddEntriesFromDictionary:myDictionary];
// Now add the data
[myMutableDictionary setObject:myObject forKey:myKey];

Can't read NSUserDefaults data between views

Disclaimer: major noob
I'm writing an arithmetic flash card app as a learning project. I have a UITabViewController with the bottom tab bar that toggles between a few different views. Everything works okay until I try to set NSUserDefault boolean values in the Settings view controller and try to read those values in the Flashcards view controller.
The settings view has a switch to enable/disable each operator (addition, subtraction, etc) and the flashcard view should randomly present a flash card if that type of operation was enabled.
I believe that my mistake is that I don't understand the key concept of data encapsulation, objects, etc. I'd appreciate any help.
Here is the Settings view controller. I'm not even sure how to put the code into this forum so this might be a laughable moment... here goes:
// settings_flashcards.h
#import <UIKit/UIKit.h>
#interface settings_flashcards : UIViewController {
UISwitch *additionSwitch;
UISwitch *subtractionSwitch;
UISwitch *multiplicationSwitch;
UISwitch *divisionSwitch;
}
#property (nonatomic,retain) IBOutlet UISwitch *additionSwitch;
#property (nonatomic,retain) IBOutlet UISwitch *subtractionSwitch;
#property (nonatomic,retain) IBOutlet UISwitch *multiplicationSwitch;
#property (nonatomic,retain) IBOutlet UISwitch *divisionSwitch;
#end
and...
/ settings_flashcards.m
#import "settings_flashcards.h"
#implementation settings_flashcards
#synthesize additionSwitch;
#synthesize subtractionSwitch;
#synthesize multiplicationSwitch;
#synthesize divisionSwitch;
- (void)viewDidLoad {
[additionSwitch addTarget:self action:#selector(additionSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[subtractionSwitch addTarget:self action:#selector(subtractionSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[multiplicationSwitch addTarget:self action:#selector(multiplicationSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[divisionSwitch addTarget:self action:#selector(divisionSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[super viewDidLoad];
}
-(void) additionSwitchFlipped {
if (additionSwitch.on) {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"additionKey"];
}else {
[[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:#"additionKey"];
}
}
-(void) subtractionSwitchFlipped {
if (subtractionSwitch.on) {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"subtractionKey"];
}else {
[[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:#"subtractionKey"];
}
}
-(void) multiplicationSwitchFlipped {
if (multiplicationSwitch.on) {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"multiplicationKey"];
}else {
[[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:#"multiplicationKey"];
}
}
-(void) divisionSwitchFlipped {
if (divisionSwitch.on) {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"divisionKey"];
}else {
[[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:#"divisionKey"];
}
}
Here is the Flashcards view...
// flashcardsViewController.h
#import <UIKit/UIKit.h>
#interface flashcardsViewController : UIViewController <UIActionSheetDelegate>{
UILabel *firstNumberLabel;
UILabel *secondNumberLabel;
UILabel *answerNumberLabel;
UILabel *operatorLabel;
BOOL additionIsEnabled;
BOOL subtractionIsEnabled;
BOOL multiplicationIsEnabled;
BOOL divisionIsEnabled;
}
#property (nonatomic,retain) IBOutlet UILabel *firstNumberLabel;
#property (nonatomic,retain) IBOutlet UILabel *secondNumberLabel;
#property (nonatomic,retain) IBOutlet UILabel *answerNumberLabel;
#property (nonatomic,retain) IBOutlet UILabel *operatorLabel;
-(void) buttonClicked:(id)sender;
#end
and...
// flashcardsViewController.m
#import "flashcardsViewController.h"
#implementation flashcardsViewController
#synthesize firstNumberLabel;
#synthesize secondNumberLabel;
#synthesize answerNumberLabel;
#synthesize operatorLabel;
- (void)viewDidLoad {
srand(time(0)); //seed random
//the following should assign the keys if they don't exist
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"additionKey"]){
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"additionKey"];
}
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"subtractionKey"]) {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"subtractionKey"];
}
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"multiplicationKey"]) {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"multiplicationKey"];
}
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"divisionKey"]) {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"divisionKey"];
}
//the following should assign each BOOL variable based on the key
additionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:#"additionKey"];
subtractionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:#"subtractionKey"];
multiplicationIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:#"multiplicationKey"];
divisionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:#"divisionKey"];
[super viewDidLoad];
}
-(void) buttonClicked:(id)sender{
int a = rand() % 4;// random number generator (number to enter loop)
if ( additionIsEnabled || subtractionIsEnabled || multiplicationIsEnabled || divisionIsEnabled) {
while (a < 5) {
switch (a) {
case 0:
if (additionIsEnabled == TRUE){
int x = rand() % 11 + 1;
int y = rand() %11 + 1;
firstNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",x];
secondNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",y];
answerNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",(x+y)];
operatorLabel.text = [[NSString alloc]initWithFormat: #"+"];
a = 5;
}
else a++;
break;
case 1:
if (subtractionIsEnabled == TRUE){
int x = rand() % 19 + 1;
int y = rand() %11 + 1;
firstNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",x];
secondNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",y];
answerNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",(x-y) ];
operatorLabel.text = [[NSString alloc]initWithFormat: #"-"];
a = 5;
}
else a++;
break;
case 2:
if (multiplicationIsEnabled == TRUE){
int x = rand() % 11 + 1;
int y = rand() %11 + 1;
firstNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",x];
secondNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",y];
answerNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",(x*y)];
operatorLabel.text = [[NSString alloc]initWithFormat: #"×"];
a = 5;
}
else a++;
break;
case 3:
if (divisionIsEnabled == TRUE){
int x = rand() % 11 + 1;
int y = rand() % 11 + 1;
firstNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",(x*y)];
secondNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",y];
answerNumberLabel.text = [[NSString alloc]initWithFormat: #"%i",x];
operatorLabel.text = [[NSString alloc]initWithFormat: #"÷"];
a = 5;
}
else a = 0;
break;
default:
break;
}
}
}
else
{
UIAlertView *noOperatorSelectedAlert = [[UIAlertView alloc]initWithTitle:#"You have not set any operations."
message:#"Return to the settings menu and decide which operations you wish to perform. (addition, subtraction, etc.)"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[noOperatorSelectedAlert show];
[noOperatorSelectedAlert release];
}
}
There are a few things to do here. Firstly you want a better way of saying what the default state is before the user has made any explicit decisions. Next you want to know when you should refresh your in-app state from user preferences.
Defaults Initialization
The first item's solution is to put the default values into the registration domain for your user preferences. This is something you'll do during application initialization, rather than having your views individually check preferences and update them at initialization time. The preferences system looks in quite a few places for data, and the first place it looks is in the in-memory-only registration domain. This is where you'll put the default (i.e. no value specified means 'x') values for each of your user preferences.
The API you'll use for this is -[NSUserDefaults registerDefaults:], which takes an NSDictionary of values. To set your default values of YES (in Objective-C the BOOL type uses YES and NO rather than TRUE and FALSE) you'll use something like this, commonly executed in a +initialize method for your application's main class:
+ (void) initialize
{
// in any +initialize, make sure it's being called on your class
// +initialize is different from all other methods in this respect
if ( [self isKindOfClass: [MyApplicationDelegate class]] == NO )
return; // being called on a superclass, don't do my stuff
// set up default values for certain preferences
NSMutableDictionary * defaults = [NSMutableDictionary new];
[defaults setObject: [NSNumber numberWithBool: YES] forKey: #"additionKey"];
[defaults setObject: [NSNumber numberWithBool: YES] forKey: #"subtractionKey"];
[defaults setObject: [NSNumber numberWithBool: YES] forKey: #"multiplicationKey"];
[defaults setObject: [NSNumber numberWithBool: YES] forKey: #"divisionKey"];
// set this as the registration domain
[[NSUserDefaults standardUserDefaults] registerDefaults: defaults];
[defaults release];
}
Usually you'll put everything into one method like this, so if you have other parts of the application which expect a default non-zero value for any preference, you should add those to this group and place it into your application delegate's +initialize method.
Now, when your other classes use [[NSUserDefault standardUserDefaults] boolForKey: #"additionKey"] and there is nothing saved to the preference files for that key, they will get the value supplied above.
Refreshing Cached Values
So, you have a view where the user is able to change these preferences. Your next job is to make the view above that update its member variables using the new preferences. For this we can use either delegation or notification. In this case, I'll go with notifications for to reasons:
You're using NSUserDefaults, which can theoretically change in many different places. Delegation would only inform you of changes made by one object.
NSUserDefaults already implements a handy notification which you can watch.
So, in your flashcardsViewController you'll have something like these few methods:
- (void) updateFromPreferences
{
// fetch current values from user defaults into your member variables
additionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey: #"additionKey"];
// etc...
}
- (void) viewWillLoad
{
// load variables from user defaults
[self updateFromPreferences];
// find out when the preferences have been changed
// this will cause -updateFromPreferences to be called
// whenever something changes preferences, inside the app or outside
[[NSNotificationCenter defaultNotificationCenter] addObserver: self
selector: #selector(updateFromPreferences)
name: NSUserDefaultsDidChangeNotification
object: nil];
}
- (void) viewDidUnload
{
// always remove notification observers.
[[NSNotificationCenter defaultNotificationCenter] removeObserver: self
name: NSUserDefaultsDidChangeNotification
object: nil];
}
- (void) dealloc
{
// add this to your existing dealloc routine
[[NSNotificationCenter defaultNotificationCenter] removeObserver: self
name: NSUserDefaultsDidChangeNotification
object: nil];
}
Summary
Taken together, these two should give you everything you need to make this work.
In addition to the "always YES" problem pointed out by Chiefly Izzy, your -buttonClicked: method does not read new values from NSUserDefaults. These values are read (once) in [flashcardsViewController viewDidLoad]. If they are changed in settings, the change will not be detected in flashCardsViewController until the next time it is loaded (probably the next time the application is launched).
The simplest approach would be to move your code for reading the IsEnabled BOOL values into the -buttonClicked method, like so:
-(void) buttonClicked:(id)sender {
// the following should assign each BOOL variable based on the key
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
additionIsEnabled = [defaults boolForKey:#"additionKey"];
subtractionIsEnabled = [defaults boolForKey:#"subtractionKey"];
multiplicationIsEnabled = [defaults boolForKey:#"multiplicationKey"];
divisionIsEnabled = [defaults boolForKey:#"divisionKey"];
int a = rand() % 4;
if ( additionIsEnabled || subtractionIsEnabled ...
This code ...
//the following should assign the keys if they don't exist
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"additionKey"]){
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"additionKey"];
}
... simply always set's additionKey to TRUE. If you would like to check if additionKey is set, do this ...
//the following should assign the keys if they don't exist
if (![[NSUserDefaults standardUserDefaults] objectForKey:#"additionKey"]){
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"additionKey"];
}
... boolForKey: documentation: If a boolean value is associated with defaultName in the user defaults, that value is returned. Otherwise, NO is returned.
Translated to human language - if there's an value associated with additionKey, this value is returned. If there's no associated value, NO/FALSE is returned.
So, your code does this - if value is not associated with additionKey or if it is set to NO, set it to YES. This leads to this - additionKey is always set to YES/TRUE.

Using NSUserDefaults for storing UISwitch state

I am trying to persist the UISwitch state in my settings view of my application. Basically it is a UITableView and contains a few switches to get the user preferences. The below code explains how the switches are constructed (only one switch construct is given below, others are also constructed the sameway).
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SomeIdentifierB] autorelease];
if (syncStartupSwitch) {
syncSwitch.on = YES;
}else {
syncSwitch.on = NO;
}
[syncSwitch addTarget:self action:#selector(syncAtStartup:) forControlEvents:UIControlEventValueChanged];
NSLog(#"Why is this not working%#",(syncSwitch.on ? #"YES" : #"NO"));
[cell.contentView addSubview:syncSwitch];
cell.accessoryView = syncSwitch;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
//cell.reuseIdentifier = #"Cell1";
}
cell.textLabel.text =cellValue;
return cell;
}
Now, I would like to store the state of the Switches using NSUserDefaults. So in my selector method implementation, I defined the NSUserDefaults like this:
-(void) syncAtStartup:(id)sender {
if ([sender isOn]) {
[[NSUserDefaults standardUserDefaults]
setObject:#"YES" forKey:#"SyncAtStartup"];
[[NSUserDefaults standardUserDefaults]synchronize];
NSLog(#"%#",(syncStartupSwitch ? #"YES" : #"NO"));
}else {
[[NSUserDefaults standardUserDefaults]
setObject:#"NO" forKey:#"SyncAtStartup"];
//syncStartupSwitch = [[NSUserDefaults standardUserDefaults]boolForKey:#"SyncAtStartup"];
}
}
Finally, in my viewDidLoad I wrote this line of code:
syncStartupSwitch = [[NSUserDefaults standardUserDefaults]boolForKey:#"SyncAtStartup"];
I am sure there is some missing logic to my implementation. Can somebody point out the flaw and correct me?
UPDATE:
I took the suggestion from #jfalexvijay and used the below code:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"SyncAtStartup"];
BOOL syncStartupSwitch = [[NSUserDefaults standardUserDefaults] boolForKey:#"SyncAtStartup"];
When I look into the Preferences folder, I see the plist getting created with the BOOL value in it. I then try to set the UISwitch state in cellForRowAtIndexPath method like this:
syncSwitch.on = syncStartupSwitch;
I also have this line of code in ApplicationWillTerminate and in the selector itself
[[NSUserDefaults standardUserDefaults]synchronize];
Still, after restarting the application on the simulator or device, the switch state is not restored...
What is my mistake in the above code?
Cheers,
iSee
you can use following code;
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"SyncAtStartup"];
BOOL test = [[NSUserDefaults standardUserDefaults] boolForKey:#"SyncAtStartup"];
if you use following code, it will return YES;
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"SyncAtStartup"];
BOOL test = [[NSUserDefaults standardUserDefaults] boolForKey:#"SyncAtStartup"];
Just test above code;
Instead of using setObject:forKey: try using setBool:forKey:.
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"SyncAtStartup"];