Having an NSUserDefault Problem - iphone

I am trying to save a couple of preferences in a program I can't seem to make NSUserDefaults work properly. If someone could take a look at my code and see if there are any errors it would be appreciated
NSString *kGameIsPaused = #"gameGameIsPaused";
NSString *kSoundOn = #"gameSoundOn";
NSString *kMusicOn = #"gameMusicOn";
NSString *kHighScore = #"gameHighScore";
- (void)saveGameState
{
[[NSUserDefaults standardUserDefaults] setBool:gameIsPaused forKey:kGameIsPaused];
[[NSUserDefaults standardUserDefaults] setBool:soundOn forKey:kSoundOn];
[[NSUserDefaults standardUserDefaults] setBool:musicOn forKey:kMusicOn];
[[NSUserDefaults standardUserDefaults] setInteger:highScore forKey:kHighScore];
}
-(void)loadGameState
{
gameIsPaused = [[NSUserDefaults standardUserDefaults] boolForKey:kGameIsPaused];
soundOn = [[NSUserDefaults standardUserDefaults] boolForKey:kSoundOn];
musicOn = [[NSUserDefaults standardUserDefaults] boolForKey:kMusicOn];
highScore= [[NSUserDefaults standardUserDefaults] integerForKey:kHighScore];
if (soundOn == NO) {
[soundToggle setImage:[UIImage imageNamed:#"SoundOFF.png"] forState:UIControlStateNormal];
}
if (musicOn == NO) {
[musicToggle setImage:[UIImage imageNamed:#"MusicOff.png"] forState:UIControlStateNormal];
}
}
they everytime i run the loadGameState method I get returned the default values as if there is no key to reference.

Inside of saveGameState I would recommend adding a synchronize to your defaults to persist them. If your game is crashing or you are stopping the debugger or anything else goes wrong they may not get saved properly.
- (void)saveGameState
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:gameIsPaused forKey:kGameIsPaused];
[defaults setBool:soundOn forKey:kSoundOn];
[defaults setBool:musicOn forKey:kMusicOn];
[defaults setInteger:highScore forKey:kHighScore];
[defaults synchronize];
}

Related

find special keys in UserDefaults by "substringToIndex"

I'm grouping my UserDefault keys by specific prefixes.
e.g.
[NSUserDefaults standardUserDefaults] setInteger: 1 forKey: #"prefix1_someText_Key"]
[NSUserDefaults standardUserDefaults] setInteger: 2 forKey: #"prefix2_someText_Key"]
[NSUserDefaults standardUserDefaults] setInteger: 3 forKey: #"prefix4_someText_Key"]
//.....
Now, I'd like to find all the keys, that start with e.g. "prefix", and load them into an array. is there a way for doing that (programmatically)?
You could use the underlying NSDictionary to find the suitable keys:
NSString *myPrefix = #"prefix";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *dict = [defaults dictionaryRepresentation];
NSMutableArray *keysWithPrefix = [NSMutableArray array]
for (NSString *key in dict.keyEnumerator) {
if ([key hasPrefix: myPrefix]) {
[keysWithPrefix addObject: key];
}
}
// now keysWithPrefix contains all matching keys
UPDATE
For debugging reasons you could add a log to see what keys are being dropped:
for (NSString *key in dict.keyEnumerator) {
if ([key hasPrefix: myPrefix]) {
[keysWithPrefix addObject: key];
} else {
NSLog(#"Dropping key %#", key);
}
}

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];

How to store a float in NSUserDefaults

I want to store a float value into NSUserDefaults.
I also need to check that the float value exists..if not I need to assign some value in it.
and retrieve it...for the above I have the below code but it gives me an error.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"HANDWRITING_SIZE_SLIDER"] == YES) {
self.sizeSlider.value = 10.0;
} else {
self.sizeSlider.value = [[NSUserDefaults standardUserDefaults] floatForKey:#"HANDWRITING_SIZE_SLIDER"]];
}
Thanks for any help
Use the NSNumber class for this and store it via the setObject:forKey: method so you can check if it exists.
I'd also suggest the usage of constants as keys:
#define HANDWRITING_SIZE_SLIDER #"HSS"
Your code should be along these lines:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:HANDWRITING_SIZE_SLIDER] == nil) {
//doesn't exist in NSUserDefaults, set to default value...
self.sizeSlider.value = 10.0;
} else {
self.sizeSlider.value = [[defaults objectForKey:HANDWRITING_SIZE_SLIDER] floatValue];
}
Somewhere else in your app, you'd set the value in NSUserDefaults like this:
float sizeSliderValue = ...
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:sizeSliderValue] forKey:HANDWRITING_SIZE_SLIDER];
Try this code:
-(IBAction)sliderAction:(id)sender
{
float sliderValue = [sender floatValue];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:sliderValue] forKey:#"keySliderValue"];
NSLog(#"%#",[[NSUserDefaults standardUserDefaults] objectForKey:#"keySliderValue"]);
}

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"];