Unable to save integer with NSUserDefaults - ios

Basically I am trying to make it so when I restart the app the score for the user is saved, currently, the score reverts to zero upon closing and reopening the app. I have looked for numerous solutions on the internet but have found nothing. Here is my code (ViewController.m):
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
int bytes;
int highScore;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
highScore = bytes;
[[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 ];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)addBytes:(id)sender {
highScore = [[[NSUserDefaults standardUserDefaults] objectForKey:#"HighScore"] intValue ];
highScore++;
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:highScore] forKey:#"HighScore"];
[_byteCounter setText:[NSString stringWithFormat:#"%d", highScore]];
}
#end

you can use this code, i hope work it for you:
[[NSUserDefaults standardUserDefaults] setInteger:HighScore forKey:#"HighScore"];

The user defaults is not being updated as you don't update it.
highscore++ only increments the your int variable, it doesn't increment the value in NSUserDefaults. So after you update highscore, you still need to update the NSUserDefaults by calling:
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:highScore] forKey:#"HighScore"];
Furthermore, you need not, and should not, call synchronize. The data will be flushed to the disk at some point later on automatically.

Upon start up I was not displaying the saved value from NSUserDefaults to the label, here is my updated code that does save the integer upon restarting the app. (I'm very proud of my self!)
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
int bytes;
int highScore;
- (void)viewDidLoad {
[super viewDidLoad];
highScore = bytes;
highScore = [[[NSUserDefaults standardUserDefaults] objectForKey:#"HighScore"] intValue ];
[_byteCounter setText:[NSString stringWithFormat:#"%d", highScore]];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:highScore] forKey:#"HighScore"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (IBAction)addBytes:(id)sender {
highScore = [[[NSUserDefaults standardUserDefaults] objectForKey:#"HighScore"] intValue ];
highScore++;
[_byteCounter setText:[NSString stringWithFormat:#"%d", highScore]];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:highScore] forKey:#"HighScore"];
}
#end

Related

Crash interacting with NSUserDefaults and NSArray

I have an NSMutableArray in which I am adding objective and storing in user defaults, but while adding it is crashing.
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"]) {
bssidObserverArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"];
}
if (bssidObserverArray.count > 0) {
if (![bssidObserverArray containsObject:vendorID]) {
NSLog(#"bssidObserverArray %#",bssidObserverArray);
// In this line app is getting crashed
[bssidObserverArray addObject:vendorID];
[[NSUserDefaults standardUserDefaults] setObject:bssidObserverArray forKey:#"bssidObserverArray"];
}
}else{
[bssidObserverArray addObject:vendorID];
[[NSUserDefaults standardUserDefaults] setObject:bssidObserverArray forKey:#"bssidObserverArray"];
}
Any suggestions would be more helpful.
Assuming bssidObserverArray is NSMutable array then come the problem here .
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"]) {
bssidObserverArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"];
}
since NSUserdefaults returns immutable. you can do like this
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"]) {
NSArray *someArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"];
bssidObserverArray = [someArray mutableCopy];
}

Objective C - Saving a variable inside NSUserDefaults

I have a class called "EntityType" that has a string "name" and I am using NSUserDefaults to save it so I tried this:
if (button.selected)
{
[button setSelected:YES];
[[NSUserDefaults standardUserDefaults]setObject:[NSNumber numberWithBool:YES] forKey:#"buttonSelected"];
}
I want to access the variable from another class and save it inside NSUserDefaults
You have missed sync call.Apply this to save it.
if (button.selected)
{
[button setSelected:YES];
[[NSUserDefaults standardUserDefaults]setObject:[NSNumber numberWithBool:YES] forKey:#"buttonSelected"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
to get it back later
NSNumber* savedValue = [[NSUserDefaults standardUserDefaults]
objectForKey:#"buttonSelected"];
This is if you want to store only the value.
If you want to store your custom object look at this link
How to store custom objects in NSUserDefaults
You can get NSNumber object like,
NSNumber *num = [[NSUserDefaults standardUserDefaults] objectForKey:#"buttonSelected"];
from anywhere in the app.
On your EntityType class, implement the following two methods for encoding and decoding (something relevant to your own object):
- (void)encodeWithCoder:(NSCoder *)encoder {
//Encode properties, other class variables, etc
[encoder encodeObject:self.name forKey:#"name"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
//decode properties, other class vars
self.name = [decoder decodeObjectForKey:#"name"];
}
return self;
}
Reading and writing from NSUserDefaults:
- (void)saveCustomObject:(MyObject *)object key:(NSString *)key {
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:encodedObject forKey:key];
[defaults synchronize];
}
- (MyObject *)loadCustomObjectWithKey:(NSString *)key {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *encodedObject = [defaults objectForKey:key];
MyObject *object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
return object;
}
Code borrowed from: save class in NSUserDefaults
**ViewController.h**
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
//here i took one userdefault property
#property(strong,nonatomic)NSUserDefaults *user;
#end
**ViewController.m**
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//after the property declaration take standard user defaults
_user = [NSUserDefaults standardUserDefaults];
//here i took Bool and key you can take any thing but took my_val
[_user setBool:YES forKey:#"my_val"];
}
// this is button action
- (IBAction)submit:(id)sender
{
//for bool i am checking the condition given above
if ([_user boolForKey:#"my_val"])
{
**enter code here**
NSLog(#"values is set to yes");
}
else
{
**enter code here**
NSLog(#"Value is set to No");
}
}

Obj C - NSUserDefaults won't give back values to calculate, after loading the view

I am stuck with little problem. I have basic calculating app.
Viewcontroller.m
#import "ViewController.h"
#interface ViewController () <UITextFieldDelegate, UIAlertViewDelegate>
#end
#implementation ViewController
-(void)textFieldDidEndEditing:(UITextField *)textField
{
self.currentSettings = _currentSettings;
[self calculateThePrice];
}
-(void)calculateThePrice
{
float wynik = self.currentSettings.kwh * self.currentSettings.price;
self.priceLabel.text = [NSString stringWithFormat:#"%.02f %#", wynik , self.currentSettings.currency];
}
SettingsVC.m
#import "SettingsVC.h"
#interface SettingsVC () <UITextFieldDelegate>
#end
#implementation SettingsVC
#pragma mark - UserDefaults Implementation
-(void)viewWillAppear:(BOOL)animated
{
[self createCurrencyArray];
NSUserDefaults *priceDef = [NSUserDefaults standardUserDefaults];
NSString *priceDefText = [priceDef stringForKey:#"priceCall"];
_priceTextField.text = priceDefText;
NSUserDefaults *currencyDef = [NSUserDefaults standardUserDefaults];
[_currencyPicker selectRow:[currencyDef integerForKey:#"currencyCall"]
inComponent:0 animated:NO];
[priceDef synchronize];
[currencyDef synchronize];
}
-(void)viewWillDisappear:(BOOL)animated
{
NSString *textOfPriceTexField = _priceTextField.text;
[[NSUserDefaults standardUserDefaults] setObject:textOfPriceTexField forKey:#"priceCall"];
}
Now, the problem is when I want program to automatically-calculate, it won't. To have any result, I have to switch to Second View, choose a value from picker and then when I will go back, I have my result.
But...
- When I change value on 1st screen, result won't change. When I change value on 2nd scree, result won't change. But when I change value on PickerView - TADAH - result updates!
When I go to second view, and go back to first, then go again to second and go back to first, my result changes to "0.00 (NULL)"...
Any ideas where I did wrong? I think it is about NSUserDefaults, I tried many options, nothing worked, nor changed anything.
You need to synchronize NSUserDefaults when you set new values. You are using synchronize when you retrieve values.
Here you don't need 2 pointers to defaults and don't need synchronize:
NSUserDefaults *priceDef = [NSUserDefaults standardUserDefaults];
NSString *priceDefText = [priceDef stringForKey:#"priceCall"];
_priceTextField.text = priceDefText;
[_currencyPicker selectRow:[priceDef integerForKey:#"currencyCall"] inComponent:0 animated:NO];
Here you need synchronizes:
-(void)viewWillDisappear:(BOOL)animated
{
NSString *textOfPriceTexField = _priceTextField.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:textOfPriceTexField forKey:#"priceCall"];
[defaults synchronize];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSInteger selectedRow = [_currencyPicker selectedRowInComponent:0];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:selectedRow forKey:#"currencyCall"];
[defaults synchronize];
self.currentSettings.currency = [self.currencyArray objectAtIndex:row];
self.currentSettings.price = [self.priceTextField.text floatValue];
//[self userDidFinishSetting];
}
Try this code
-(void)viewWillDisappear:(BOOL)animated
{
NSString *textOfPriceTexField = _priceTextField.text;
[[NSUserDefaults standardUserDefaults] setObject:textOfPriceTexField forKey:#"priceCall"];
}
-(void)viewWillAppear:(BOOL)animated
{
[self createCurrencyArray];
NSUserDefaults *priceDef = [NSUserDefaults standardUserDefaults];
NSString *priceDefText = [priceDef objectForKey:#"priceCall"];
}
instead of stringForKey you can call objectForKey same as for integerForKey also you can call objectForKey. Actually you are setting the object not string or integer.

NSCoding save NSMutableArray on shutdown and load on startup

I am trying to save a NSMutableArray when the app shuts down, and then load it on startup to a tableview.
Here's my code:
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:_savedText forKey:#"savedText"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super initWithCoder:decoder])) {
_savedText = [decoder decodeObjectForKey:#"savedText"];
}
return self;
}
I use this code to save the MutableArray:
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:_savedText];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:#"savedText"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
And this to load it:
- (void)viewDidLoad {
NSData *savedData = [[NSUserDefaults standardUserDefaults] objectForKey:#"savedText"];
NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:savedData];
array = [_savedText copy];
}
There are no errors, but the table view is empty on startup. Have I forgotten something?
You should read the data from the defaults and set to _savedText object. You are reading the data into var named array and then assigning array = [_savedText copy]. This will probably be nil. It should be the reverse.
- (void)viewDidLoad {
NSData *savedData = [[NSUserDefaults standardUserDefaults] objectForKey:#"savedText"];
NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:savedData];
_savedText = [array copy];
}

Adding to a Previously saved NSUserDefaults

I am making a game for iOS which in includes a scoring system in each level. Here I have some code that gets an NSString (passedValue1) by using a delegate.
Heres the code for the delegate:
LevelCompleteLevel1
.h
#import "ViewController.h"
#interface LevelCompleteLevel1 : UIViewController{
IBOutlet UILabel *label;
ViewController *secondviewData;
}
#property (nonatomic, retain)ViewController*secondviewData;
.m
ViewController *second = [[ViewController alloc] initWithNibName:nil bundle:nil];
self.secondviewData = second;
secondviewData.passedValue1 = label.text;
[self presentModalViewController:second animated:YES];
In the .m I send the a value from a label in the current viewcontroller to another view controller the value I send is called passedValue1
Once I have sent the value I need to display and save in my ViewController
ViewController
.h
#interface ViewController : UIViewController{
IBOutlet UILabel *label;
NSString *passedValue1;
}
#property (nonatomic, retain)NSString *passedValue1;
#end
.m
Firstly I ... #synthesize passedValue1;
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
NSString *key=#"labelKey";
// Do any additional setup after loading the view, typically from a nib
if(passedValue1){
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSObject * object = [prefs objectForKey:key];
if(object != nil){
NSUserDefaults *defults = [NSUserDefaults standardUserDefaults];
[defults setObject:passedValue1 forKey:key];
[defults synchronize];
}
else{
NSUserDefaults *defults = [NSUserDefaults standardUserDefaults];
NSInteger readScore=[[[NSUserDefaults standardUserDefaults] objectForKey:key] integerValue];
NSInteger newValue=readScore+[passedValue1 integerValue];
[defults setObject:[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.
Thanks in advance.
edit
Iam using this code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib
NSString *key=#"labelKey";
// Do any additional setup after loading the view, typically from a nib
if(passedValue1){
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSObject * object = [prefs objectForKey:key];
if(object != nil){
NSUserDefaults *defults = [NSUserDefaults standardUserDefaults];
[defults setObject:passedValue1 forKey:key];
[defults synchronize];
}
else{
NSUserDefaults *defults = [NSUserDefaults standardUserDefaults];
NSInteger readScore=[[[NSUserDefaults standardUserDefaults] objectForKey:key] integerValue];
NSInteger newValue=readScore+[passedValue1 integerValue];
[defults setValue:[NSString stringWithFormat:#"%d",newValue] forKey:key];
[defults synchronize];
}
}
label.text = [[NSUserDefaults standardUserDefaults]objectForKey:key];
}
Why is this not working , the displayed value of the label is the originally passedValue1?
once try this one ,
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:#"10" forKey:#"old value"];
[defaults synchronize];
int k=[[defaults objectForKey:#"old value"] intValue]+newValue;
Two things
As you are adding the NSString it is enough to use the setValue: forKey: method. (NOT setObject:forKey as you are using)
NSUserDefaults is a key based value saving mechanism. If you try to save the value in the same key the saved value will be replaced by the current saving value.
So in your case just call for the same key with the new value and you have the older value replaced with new one.

Resources