save bool in nsuserdefaults - objective-c

when my app starts music is playing:
-(void)playBgMusic {
NSString *path = [[NSBundle mainBundle] pathForResource:#"bgmusic" ofType:#"aif"];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play]; }
but he should be able to turn the music off by pressing a button if he presses the button again the music should turn on again. i have:
-(IBAction)check {
if (isquiet == NO) {
[theAudio stop];
isquiet = YES;
defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:YES forKey:#"stringKey"];
}
else {
[self playBgMusic];
isquiet = NO;
defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:NO forKey:#"stringKey"]; } }
I think I didn't get it. Now it works in my first ViewController that I can turn the music on and off but when I go to another viewController while the music is playing, then back again and press the button, the music doesn't stop and when i press it many times the music is played a second time and overlaps.
What's still wrong?

No need to wrap it in an NSNumber, there are some convenience methods for this:
To set a BOOL, use:
[userDefaults setBool:YESorNO forKey:#"yourKey"];
To access it, use:
[userDefaults boolForKey:#"yourKey"];
[EDIT TO ANSWER YOUR ADDITIONAL QUESTION]
Not sure why you are using NSUserDefaults - it seems unnecessary for what you are trying to achieve? Here's what I would do for a button that can start/stop music:
-(IBAction)check
{
if (isQuiet)
{
// Play music
// Change the button to indicate it is playing...
} else
{
// Stop music
// Change the button to indicate it has stopped...
}
// Set your isQuiet to be the opposite of what it was when the button was clicked
isQuiet = !isQuiet;
}

Box your BOOL value to NSNumber object and add it to NSUserDefault:
NSUserDefaults *boolUserDefaults = [NSUserDefaults standardUserDefaults];
[boolUserDefaults setObject:[NSNumber numberWithBool:isquiet]
forKey:#"stringKey"];
Later you'll be able to retrieve that value as plain BOOL using -boolForKey: function in NSUserDefaults

To save:
[boolUserDefaults setObject:[NSNUmber numberWithBool:isQuiet] forKey:#"stringKey"];
When you read it back, read it as a NSNumber then do:
BOOL savedIsQuiet = [theNumberYouSaved boolValue];

Swift:
To save bool:
UserDefaults.standard.set(true, forKey: "storageKey")
To retrieve the bool:
let boolValue = UserDefaults.standard.bool(forKey: "storageKey")

Related

How to load the user’s last selected value for a slider when the app relaunches?

I am new to Xcode and I am using Objective C in OSX.
I am trying to load the user’s last selected value for a slider when the app relaunches.
my code for the slider is…
- (IBAction)sliderChanged:(id)sender {
amount = [self.amountSlider integerValue];
NSString *amountString = [NSString stringWithFormat:#"%ld", amount];
[self.amountLabel setStringValue:amountString];
}
I have this setter…
- (void)setInteger:(NSInteger)valueforKey:(NSString *)defaultName{
[[NSUserDefaults standardUserDefaults] setObject:#"amountString" forKey:#"amountSlider"];
}
I would like to know how to code the getter.
A step-by-step instructions with code will be appreciated.
Any improvements/corrections to my existing code above would also be appreciated.
Make separate functions for retrieving, saving from defaults like this.
- (void)saveValueToUserDefaults:(NSString *)pValue key:(NSString *)kKey {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[self removeValueFromUserDefaults:kKey];
[defaults setObject:pValue forKey:kKey];
[defaults synchronize];
}
- (void)removeValueFromUserDefaults:(NSString *)kKey {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:kKey]) {
[defaults removeObjectForKey:kKey];
}
}
- (NSString *)retriveValueFromUserDefaults:(NSString *)kKey {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:kKey]) {
return [defaults objectForKey:kKey];
} else {
return kStringEmpty;
}
}
This will make simple to save and retrieve values from defaults.
Like-
[self saveValueToUserDefaults:YOUR_AMOUNT forKey:YOUR_KEY];
and get like this,
YOUR_AMOUNT = [self retriveValueFromUserDefaults:YOUR_KEY];
You asked for it :D
in your class create integer variable called amountChecker = 0
create a function called checker like this :
-(void) checker {
if (amount == amountChecker){
[[NSUserDefaults standardUserDefaults] setObject:amountLabel.text forKey:#"amountSlider"];
}
else
amount = amountChecker;
}
then .. in this function :
- (IBAction)sliderChanged:(id)sender {
amount = [self.amountSlider integerValue];
NSString *amountString = [NSString stringWithFormat:#"%ld", amount];
[self.amountLabel setStringValue:amountString];
[self performSelector:#selector(checker) withObject:nil afterDelay:1];
}
now this code will only store your value if a second passes and your slider didn't change , instead of storing your value like 60 times every second :D
it all starts when you change the slider then after one second it will check if the value changed if not it will store it
and when you reopen the app you will use this code :
amount = [[NSUserDefaults standardUserDefaults] objectForKey:#"amountSlider"];

How to save fields correctly with NSUserDefaults?

I'm creating a program that saves a String from one text field and an integer from a second text field. I am trying to use NSUserDefaults, but I can't seem to get either of them to save correctly when I run the program. It crashes when I press the save button with the breakpoint while handling the NSUserDefaults. Am I doing something wrong? I skimmed through the documentation, but it didn't help. Can I even use 2 different instances of NSUserDefaults?
- (IBAction)save:(id)sender {
//Save stuff fropm textfields
NSString* name = _nameText.text;
int count = [_countText.text intValue];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[[NSUserDefaults standardUserDefaults] setObject:name forKey:#"name"];
[[NSUserDefaults standardUserDefaults] setInteger:count forKey:#"count"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (IBAction)load:(id)sender {
//Load stuff from NSUserDefaults
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSString* loadstring = [defaults objectForKey:#"name"];
_nameText.text = loadstring;
NSUserDefaults* defaults2 = [NSUserDefaults standardUserDefaults];
NSInteger loadint = [defaults2 integerForKey:#"count"];
_countText.text = [NSString stringWithFormat:#"%li", (long)loadint];
}
Declare defaults = [NSUserDefaults standardDefaults]; in your viewDidLoad (and NSUserDefaults* defaults; in .h) and use this code:
- (IBAction)save:(id)sender {
//Save stuff fropm textfields
NSString* name = _nameText.text;
int count = [_countText.text intValue];
[defaults setObject:name forKey:#"name"];
[defaults setInteger:count forKey:#"count"];
[defaults synchronize];
}
- (IBAction)load:(id)sender {
//Load stuff from NSUserDefaults
_nameText.text = [defaults stringForKey:#"name"];
_countText.text = [NSString stringWithFormat:#"%li", (long)[defaults integerForKey:#"count"]];
}

save and load highscore

i tried to use NSUserDefults to save and load a highscore(nsinteger) for my game.
i created an void function that check if the gameoverscore is bigger than my highscore and if it does to switch between them. i want that every time the game is over there will be a label which show my currect highscore.
to do this, i create a property for my NSUsweDefults, in my viewdidload i tried to load the currect highscore, and another function (checkIfHighscore).
here is my NSUserDefults property:
#property(readwrite) NSUserDefaults *prefs;
here is my viewdidload code:
NSInteger currectHighscore = [prefs integerForKey:#"highscore"];
highScoreLabel.text = [NSString stringWithFormat:#"%d",currectHighscore];
here is my checkIfHighscore:
-(void)checkIfHighScore
{
if(gameOverScore > highScore)
{
highScore = gameOverScore;
[self newHighscoreAnimation];
[prefs setInteger:highScore forKey:#"highscore"];
[prefs synchronize];
}
highScoreLabel.text = [NSString stringWithFormat:#"Highscore: %d", highScore];
}
when i enter to this viewcontroller my highscorelabel shows 0, like it doesnt save my highscore.
what do i do wrong?
thanks!
// Snippet used to save your highscore in the prefs.
int highScore = yourGameScore;
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:highScore] forKey:#"HighScore"];
[[NSUserDefaults standardUserDefaults] synchronize];
// Snippet used to get your highscore from the prefs.
highScore = [[[NSUserDefaults standardUserDefaults] objectForKey:#"HighScore"] intValue ];

Cocoa Preferences Overwritten

I have a couple questions regarding application preferences using NSUserDefaults.
In my last app I would link my preferences using bindings to NSUserDefaults, and this worked perfectly. In the application startup methods I could then perform actions based on the values stored in the NSUserDefaults.
The problem occured when I updated my application and re-distributed it, in which all the settings would get over-written with the preferences in my computer. So if someone changed the settings, and then received the update, their settings would get over-written with mine.
Looking back at the Apple documentation in regards to saving Preferences, I notice the following line which I didn't use, which is used to write preferences to disk:
[defaults synchronize];
My question is, does this code write the preferences to the user's harddrive, so that if I re-distribute the application with different settings, NSUserDefaults will read from the disk instead?
Sorry for the misunderstanding but I can't find an answer.
Thanks in advance everyone.
If you want to use bindings to control your preferences, you should be using NSUserDefaultsController. In either case, to set initial values for your defaults, you should create a dictionary with the initial values and then pass it to registerDefaults: if you're using vanilla NSUserDefaults, or one of initWithDefaults:initialValues: or setInitialValues: if you're using NSUserDefaultsController. Here's an NSUserDefaultsExample:
- (void)applicationDidFinishLaunching {
// For decent-sized applications, I normally like to store this in its own plist
// but I'm creating it in-line here for readability's sake.
NSDictionary *initialPreferences = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger:21], #"UserAge",
#"red", #"FavoriteColor",
#"Idaho", "Location", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:initialPreferences];
}
NSUserDefaults are only written when synchronize is called.
When you ship your app and you want specific settings in place at first launch, you need to set these yourself in code. I usually look for a nil value for a specific key and if it an empty value, I will set the desired "default" value.
Example
I do this when the application launches:
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
/* count how many times the user has launched the app */
int total = [[defaults objectForKey:#"kLaunchCount"] intValue]; total++;
[defaults setObject:[NSNumber numberWithInt:total] forKey:#"kLaunchCount"];
/* User chose to reset Scanner Feed, remove the .plist from Documents directory. */
if ( [[defaults objectForKey:#"kResetScannerFeeds"] boolValue] == YES ){
[[NSFileManager defaultManager] removeItemAtPath:SCANNERFEED error:nil];
[defaults setObject:[NSNumber numberWithBool:NO] forKey:#"kResetScannerFeeds"];
}
/* Check to see if Default Prefs are NULL, if so, enable them. */
if ( [defaults objectForKey:#"kShakeToToggleVisibility"] == nil ){
[defaults setObject:[NSNumber numberWithBool:YES] forKey:#"kShakeToToggleVisibility"];
}
if ( [defaults objectForKey:#"kBackgroundAudio"] == nil ){
[defaults setObject:[NSNumber numberWithBool:YES] forKey:#"kBackgroundAudio"];
}
if ( [defaults objectForKey:#"kUseMyLocation"] == nil ){
[defaults setObject:[NSNumber numberWithBool:YES] forKey:#"kUseMyLocation"];
}
if ( [defaults objectForKey:#"kAttachTwitterIcon"] == nil ){
[defaults setObject:[NSNumber numberWithBool:YES] forKey:#"kAttachTwitterIcon"];
}
if ( [defaults objectForKey:#"kAttachTwitterLink"] == nil ){
[defaults setObject:[NSNumber numberWithBool:YES] forKey:#"kAttachTwitterLink"];
}
/* User chose to log out of Facebook Session, do that now. */
if ( [[defaults objectForKey:#"kLogoutFacebook"] boolValue] == YES ){
[defaults setObject:[NSNumber numberWithBool:NO] forKey:#"kLogoutFacebook"];
[self fbLogout];
}
[defaults synchronize];

AVAudioPlayer and NSUserDefaults

[PlaySound stop];
[PlaySound prepareToPlay];
[[NSUserDefaults standardUserDefaults] synchronize];
text = [[NSUserDefaults standardUserDefaults] stringForKey:#"defaulttext"];
NSLog(#"%#",text);
BOOL loop = [prefs boolForKey:#"switch"];
NSLog(#" %d",loop);
do {
[PlaySound play];
} while (loop ==YES);
There are two major problems I am facing with this code.
1) This is a function which is called when a button is tapped... I am allocating the audio player in this function. Whenever this function is called I called the stop function on audio player yet it does not stop and two sounds play simultaneously.
2) My defaults are not registering correctly. Both the string and bool are showing nil in console.
I haves added settings bundle in my app.
Edit: Rest of the method
NSUInteger selectedRow= [SoundPicker selectedRowInComponent:0];
NSString *userchoice =[self pickerView:SoundPicker titleForRow:selectedRow forComponent:0];
NSString *soundpath = [[NSBundle mainBundle] pathForResource:userchoice ofType:#"wav"];
NSURL *fileURl = [[NSURL alloc] initFileURLWithPath:soundpath];
NSError **error = nil;
PlayFartSound = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURl error:error];
I have sorted the problem of audio player.
Can anyone please help on NSUserDefaults.
In my settings root plist I have a text field with identifier name name_preference so I put this in code:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
text = [defaults stringForKey:#"name_preference"];
NSLog(#"%# abc",text);
The log is (null) abc ? [I have set the default value to hello in plist]
How are you setting the default values in your NSUserDefaults? You say you've got the defaults in a plist, but when do you load that plist into NSUserDefaults?
To set the default NSUserDefaults values, you need to call this somewhere early in your program, ideally in somewhere like applicationDidFinishLaunching
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
Where 'defaults' is a dictionary of default settings, possibly loaded from a plist.