iOS UIStepper & NSUserDefaults - How to manage them together and use a double - ios

I have the following code. However, the line
stepper.value = [NSNumber numberWithDouble:loadNumber];
errors with the error 'Sending NSNumber *__strong to a parameter of incompatible type 'double''. I think the stepper will only accept a double, but am unsure what I am doing wrong to set it.
What I need to achieve is the following:-
1) Have a default value set in NSUserDefaults for saveNumber, which will be used until a variation is made by the user.
2) on load or view appearing, use saveNumber to set the value of both stepper.value and myLabel.
3) ensure that when changed with the stepper, the value is updated in myLabel, and NSUserDefaults saveNumber is also updated.
Can anyone advise where I am going wrong, and help correct my code please?
Further,I just realised that in the final app, I will have this setting on a different viewController to the one that will use the NSUserDefaults savedNumber value. With this in mind, can you also let me know how to ensure that savedNumber is available not only to this viewController, but any other one I require the values on?
Many thanks.
- (void)viewWillAppear:(BOOL)animated
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSNumber *loadNumber = [defaults objectForKey:#"saveNumber"];
self.myLabel.text = [NSString stringWithFormat:#"%#",loadNumber];
UIStepper *stepper = [[UIStepper alloc] init];
stepper.value = [NSNumber numberWithDouble:loadNumber];
}
- (IBAction)stepChanged:(id)sender {
NSNumber *saveNumber = [NSNumber numberWithDouble:[(UIStepper *)sender value]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveNumber forKey:#"saveNumber"];
[defaults synchronize];
self.myLabel.text = [NSString stringWithFormat:#"%#",saveNumber];
}
I have one outstanding issue which is that I cannot get the defaults to deliver if no value has been set!
I have the following code in AppDelegate.m:-
NSDictionary *defaults = #{ #"saveNumber": #8 };
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
When the App first launches (and every time after until the stepper has been used) the value being seen is 'null'.
Any ideas?

This:
stepper.value = [NSNumber numberWithDouble:loadNumber];
needs to be:
stepper.value = [loadNumber doubleValue];
And you don't need to call synchronize after setting the value in NSUserDefaults.
A value stored in NSUserDefaults can be accessed from any class, not just the class that sets it.
Update:
To set a default value you want the following:
NSDictionary *defaults = #{ #"saveNumber": #6 };
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
This will set a default value of 6 for #"saveNumber".

Related

UILabel text not being stored in NSUserDefault

I have a UILabel called 'labelA'. In this label is the letter 'A'.
When I am using NSUserDefault and start my app, the label is empty, but I don't know why?
Here is my ViewController.m file:
- (void)viewDidLoad {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
self->labelA.text = [defaults objectForKey:#"labelAtext"]; }
- (void)defaults {
NSString *textLabelA = labelA.text;
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:textLabelA forKey:#"labelAtext"];
[defaults synchronize];
}
Here is my NSString in the ViewController.h file
NSString *textLabelA =#"A";
When i load my app without NSUserDefault the labelA.text = A.
does anybody know what's my problem. Thanks a lot :-)
Your method defaults is not being called anywhere, so the text value is never stored in NSUserDefaults.
[self defaults]; // This needs to be called somewhere before you try and access NSUserDefaults.
You should also be accessing self using dot notation, not ->
self.labelA.text = [defaults objectForKey:#"labelAText"];
-> is for dereferencing a struct in C, for more information - What is "->" in Objective C?
When you use UserDefaults. You should first test if you get a value as if the value doesnt exist you need to set it or not.
NSString * myPreference = #"labelAtext";
- (void)viewDidLoad {
NSUserDefaults* userDefault = [NSUserDefaults standardUserDefaults];
id labelValue = [userDefault objectForKey:myPreference];
if (labelValue) // if preference exist
self.labelA.text = labelValue; // set ur label
else
[self storeDefaultValue]; // you store a default value
}
- (void)storeDefaultValue
{
NSString *myDefaultValue = nil;
if ([self.labelA.text isNotEqualToString:#""]) // if ur label not empty
myDefaultValue = self.labelA.text;
else
myDefaultValue = #"Not Available"; // or whatever defaults value you want
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:myDefaultValue forKey:myPreference];
[defaults synchronize];
}
What do you really want to achieve as I don't really understand whats the point of storing a value in preference as soon as you load your app. Give more details on what is your goal.

How would I be able to save an integer when an app is terminated and then load it again once the app is reopened?

I am working on an app where I need to save one int until the player decides to play the game again. It would be greatly appreciated if someone could guide me by using NSUserDefaults to save this integer whenever the application is terminated, and then be able to load it again as soon as the application loads. If there is any further information that is needed to help you help me just let me know! Thanks in advance!
You cannot save an int, you will need to convert it to an NSNumber. Use:
NSNumber *number = #(myInt);
Then you can save it (when the app terminates in your appDelegate's applicationWillTerminate:) using:
[[NSUserDefaults standardUserDefaults] setObject:number forKey:#"number"];
[[NSUserDefaults standardUserDefaults] synchronize];
To retrieve the value use:
NSNumber *number = [[NSUserDefaults standardUserDefaults] stringForKey:#"number"];
As pranav told you can store int as NSNumber or you can store it as a String, Following will work fine with NSNumber object,
int a = 10;
NSNumber *myNumber = [NSNumber numberWithInt:a];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:myNumber forKey:#"storedInt"];
NSLog(#"stored number object %#", [defaults objectForKey:#"storedInt"]); // retrieve value from NSUserDefaults
//then change NSNumber object to int value - if required
int retrievedInt = [myNumber intValue];
NSLog(#"int value %u", retrievedInt);

UIStepper - Set value from NSUserDefaults

I have the following code below which uses a stepper to set the value of the myLabel.
I have it set to store the value to NSUserDefaults.
1) I also need to set the stepper value to the same figure as that which I have put into the label. Can someone advise how to do this please? (I have added a comment to the code where I feel this should be.)
2) I would also like to check before loading the saveString that it is actually set, and if not, set a default value. Could you also advise how to achieve this?
Thanks.
- (void)viewWillAppear:(BOOL)animated
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *loadString = [defaults objectForKey:#"saveString"];
self.myLabel.text = loadString;
// Need to set the stepper value to that in loadString
}
- (IBAction)stepChanged:(id)sender {
NSString *saveString = [NSString stringWithFormat:#"%d",
[[NSNumber numberWithDouble:[(UIStepper *)sender value]] intValue]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveString forKey:#"saveString"];
[defaults synchronize];
self.myLabel.text = saveString;
}
I have updated the code as follows:-
- (void)viewWillAppear:(BOOL)animated
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSNumber *loadNumber = [defaults objectForKey:#"saveNumber"];
self.myLabel.text = [NSString stringWithFormat:#"%#",loadNumber];
UIStepper *stepper = [[UIStepper alloc] init];
stepper.value = [NSNumber numberWithDouble:loadNumber];
}
- (IBAction)stepChanged:(id)sender {
NSNumber *saveNumber = [NSNumber numberWithDouble:[(UIStepper *)sender value]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveNumber forKey:#"saveNumber"];
[defaults synchronize];
self.myLabel.text = [NSString stringWithFormat:#"%#",saveNumber];
}
However, the line 'stepper.value = [NSNumber numberWithDouble:loadNumber];' errors with the error 'Sending 'NSNumber *__strong" to a parameter of incompatible type 'double''. I think the stepper will only accept a double, but am unsure what I am doing wrong to set it.
What I need to achieve is the following:-
1) Have a default value set in NSUserDefaults for saveNumber, which will be used until a variation is made by the user.
2) on load or view appearing, use saveNumber to set the value of both stepper.value and myLabel.
3) ensure that when changed with the stepper, the value is updated in myLabel, and NSUserDefaults saveNumber is also updated.
Can anyone advise where I am going wrong, and help correct my code please?
Further, something I just realised as I am typing this is that in the final app, I will have this setting on a different viewController to the one that will use the NSUserDefaults savedNumber value. With this in mind, can you also let me know how to ensure that savedNumber is available not only to this viewController, but any other one I require the values on?
Many thanks.
Regarding question 1:
Just make one instance variable int stepper; (in your .h)
then in viewWillAppear set this variable as you do at the moment; and set
stepper = [defaults integerForKey:#"stepper"];
In your IBAction just call
stepper++;
self.myLabel.text = [NSString stringWithFormat:#"%i",stepper];
and save it in your NSUserDefaults.
Regarding question 2: NSUserDefaults offers the possibility to register defaults for certain keys, have a look at this:
NSDictionary *defaults = [NSDictionary dictionaryWithObjectsAndKeys:
#"test", #"key",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
If there is nothing set in the NSUserDefaults, the objectForKey method will return nil, so your loadString will be nil.
Now, you could convert the value you saved from a string into a number, something like [loadString floatValue];, but a probably better way would be to store an NSNumber into the userDefaults with the correct value, and recreate your label text with stringWithFormat method.

`NSUserDefaults` not saving float properly

I am building an application in which I want to save some user data by using NSUserDefaults, and it is a property of one of my controllers as following:
#property (nonatomic, strong) NSUserDefaults *userPreference;
#synthesize userPreference = _userPreference;
And I am trying to save something called a scale that should be a float, so I do something like this in the getter to put in some default values of scale in case user did not enter one:
if (!_userPreference) {
_userPreference = [NSUserDefaults standardUserDefaults];
}
if (![_userPreference floatForKey:#"scale"]) {
// if user has not entered this info yet
// also 0 is not a valid value so I can do this
[_userPreference setFloat:100.0 forKey:#"scale"]; // let default scale be 100.0
[_userPreference synchronize];
}
However, when I later on query this, no matter what I set in the default value, the following command:
[self.userPreference floatForKey:#"scale"];
always return 1. I am not sure what is happening. Am I not creating the NSUserDefaults correctly?
Thank you in advance!
if you want to use NSUserDefaults, do not create any variables or #propertys. Just use
[[NSUserDefaults standardUserDefaults] setFloat:forKey:]
[[NSUserDefaults standardUserDefaults] synchronize];
to save your data and
[[NSUserDefaults standardUserDefaults] floatForKey:]
for fetching data.
Store using
[_userPreference setObject:[NSNumber numberWithFloat:100.0] forKey:#"Scale"];
[_userPreference synchronize];
and retrieve it using
float value = [[_userPreference objectForKey:#"Scale"] floatValue];
Have you tried this to set the float value:
[_userPreference setObject:[NSNumber numberWithFloat:100.0f] forKey#"scale"];
and the following to retrieve:
CGFloat scale = [[_userPreference objectForKey#"scale"] floatValue];
Change your if condition to this:
if ([_userPreference floatForKey:#"scale"] == 0.0f ) {
NSUserDefaults will always return 0.0f if no value is set for the key. Since you are saying that "also 0 is not a valid", you can safely use this approach
try this
-(void) saveFloatToUserDefaults:(float)x forKey:(NSString *)key {
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setFloat:x forKey:key];
[userDefaults synchronize];
}
-(float) retriveFromUserDefaultsForKey:(NSString *)key {
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
return [userDefaults floatForKey:key];
}
[self saveFloatToUserDefaults:6.55 forKey:#"myFloat"];
float x = [self retriveFromUserDefaultsForKey:#"myFloat"];

How to add to a saved NSUserDefault?

I am making a game in Xcode which in includes a scoring system in each level. Here I have some code that gets an NSString (passedValue1) by using a delegate.
Then i add the code to receive the value in my viewDidLoad and display my value in a UILabel
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib
// Do any additional setup after loading the view, typically from a nib
NSString *key=#"labelKey";
if(passedValue1){
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSObject * object = [prefs valueForKey:key];
if(object != nil){
NSUserDefaults *defults = [NSUserDefaults standardUserDefaults];
[defults setValue:passedValue1 forKey:key];
[defults synchronize];
}
else{
NSUserDefaults *defults = [NSUserDefaults standardUserDefaults];
NSInteger readScore=[[[NSUserDefaults standardUserDefaults] valueForKey:key] integerValue];
NSInteger newValue=readScore+[passedValue1 integerValue];
[defults setValue:[NSString stringWithFormat:#"%d",newValue] forKey:key];
[defults synchronize];
}
}
label.text = [[NSUserDefaults standardUserDefaults]objectForKey:key];
}
Once I have displayed the value I then save it into a label using a NSUserDefault. However, once I have replayed my game and have another score value I would like to add the new passedValue1 value to the currently saved value...
For example:
say I play my level and I get the score value of 10. The value is then saved and I replay my level. I would then like to take the saved value and add it to the value i just scored. So thats say the second value I have scored is 20. I would then like my code to add them together and give me a value of 30.
can anyone help because the code I'm using does not correctly do the function that I want to do which is add the previous and the currently passed value.
What is wrong with my code??
Thanks in advance.
You shouldn't use valueForKey: for this (it's not what you might think it is, see Key-Value Coding). Instead, you should use objectForKey: or in your case integerForKey:.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger value = [defaults integerForKey:key];
value += [passedValue1 integerValue];
[defaults setInteger:value forKey:key];
BOOL success = [defaults synchronize];
It seems that you got your if condition wrong, it should be
if (object == nil) { // <-- you have object != nil here !
// save new value
} else {
// read old value, add something, save new value
}

Resources