Access an NSUserDefault from multiple views - ios

I am trying to access an NSUserDefault called prefs from multiple views. I am allocating prefs in one view but I don't know how to access it without just reallocating a new NSUserDefault in the second view.
Also, my operating system is ios.
Here is my FlipSideViewController Function:
The function in my FlipSideViewController: 'NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- (IBAction) changeRate:(id)sender {
if (rate.selectedSegmentIndex == 1){
[prefs setInteger:1 forKey:#"myRate"];//save
}
else if (rate.selectedSegmentIndex == 2){
[prefs setInteger:2 forKey:#"myRate"];//save
}
[[NSUserDefaults standardUserDefaults] synchronize];
};
And this is the MainViewController function:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// [prefs setValue: #"0" forKey: #"myRate"];
if (!([prefs valueForKey: #"myRate"])){
[prefs setInteger:0 forKey: #"myRate"];
}
[prefs setInteger:2 forKey: #"myRate"];
int rateOption = [[prefs valueForKey: #"myRate"] intValue];
if (rateOption == 1)
{
dayOrHourly.text = #"% of Day:";
percentOrHours.hidden = YES;
hours.hidden = YES;
dayPercentage.hidden = NO;
}
else if (rateOption == 2)
{
dayOrHourly.text = #"# of Hours:";
percentOrHours.hidden = NO;
dayPercentage.hidden = YES;
}

Having more than one prefs for different views shouldn't be a problem. Just call
[prefObject synchronize];
when you modify one of the instances of NSUserDefaults in one view or try to access them from another view and you'll be fine.
But if you really want to keep a single object shared across all your view controllers, put it in your App Delegate. [I must say, I don't see the point...]

NSUserDefaults is a singleton class. You're not allocating instances of it, you're accessing it.
That said, have you tried using objectForKey instead of valueForKey? Values can't return values, (... valueForKey] intValue];) whereas objects do indeed return values.
Additionally, here's how I'd do it.
First, I'd define a constant in a global header, like so:
#define kSettings [NSUserDefaults standardUSerDefaults];
Then, you should be just fine accessing NSUserDefaults across views:
[kSettings setObject:#"This is a test." forKey:#"TestString"];
to read out the string, you would do this:
[kSettings objectForKey:#"TestString"];
I suggest defining some "global constants" for accessing objects stored in NSUserDefaults. For example:
#define kTestString [kSettings objectForKey:#"TestString"];

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.

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
}

Sharing a NSString between two views

I need to share a string between two views in my application. When the user ends the game, the score is converted into a string. I then need to transfer that string into a different view controller where I display the score. I have a label set up and all but the view is not recognizing the string even though I am importing the header file from which the string is created. Any help would be great, thank.
This is my view controller where the string is created
NSString *scoreString = [NSString stringWithFormat:#"%d", score];
And this is where I try to display the string in a different view controller
- (void)viewDidLoad {
self.scoreString = score.text;
[super viewDidLoad];
}
For scores and similar data, you may want to use NSUserDefaults. These can be accessed at any time from any UIViewController. For example, you can implement methods similar to these to save and retrieve the data:
-(void)saveToUserDefaults:(NSString*)myString
{
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
if (standardUserDefaults) {
[standardUserDefaults setObject:myString forKey:#"Score"];
[standardUserDefaults synchronize];
}
}
-(NSString*)retrieveFromUserDefaults
{
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *val = nil;
if (standardUserDefaults)
val = [standardUserDefaults objectForKey:#"Score"];
return val;
}
NSUserDefaults also handles ints, BOOLs, NSArrays, etc. Check out the documentation or google around for examples.
You could use delegates or NSUserDefaults
Been asked similiar questions before:
Passing variables to different view controllers
How do I pass variables between view controllers?
EDIT
[[NSUserDefaults standardUserDefaults] setObject:#"STRING HERE" forKey:#"MyKey"];
and retrieve
[[NSUserDefaults standardUserDefaults] objectForKey:#"MyKey"];

Resources