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.
Related
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
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");
}
}
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.
I have a tableview that show saved data, but when I try to go from selected cell, it doesn't show the data that's been saved. It try this
I used NSUserDefaults to save data in other view (another .m file)
- (IBAction)saveCourseDetail:(id)sender
{
NSMutableDictionary *courseDictionary=[NSMutableDictionary new];
[courseDictionary setObject:courseName.text forKey:#"courseName"];
[courseDictionary setObject:courseDescription.text forKey:#"courseDescription"];
[courseDictionary setObject:classRoom.text forKey:#"classRoom"];
[courseDictionary setObject:teacherName.text forKey:#"teacherName"];
[courseDictionary setObject:buildingName.text forKey:#"buildingName"];
[globArray addObject:courseDictionary];
NSUserDefaults *savedData=[NSUserDefaults standardUserDefaults];
[savedData setObject:globArray forKey:#"array"];
// [savedData setObject:courseDictionary forKey:#"courseDictionary"];
[savedData synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:#"CourseAddedNotification" object:nil];
[self.navigationController popViewControllerAnimated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CourseDetailViewController *courseDetails=[[CourseDetailViewController alloc]init] ;
courseDetails.savedDataDic = [globArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController: courseDetails animated:YES];
}
My problem is that I cant go from a selected cell to the view that the data's been saved.
I personally recommend you to use core data if there is large amount of data to be stored. Using user defaults is not good to store large chunks of data. Anyways, if you want to store an array of dictionary, you have to encode it and to read the array you have to decode it like this
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *arr = ... ; // set value
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
[defaults setObject:data forKey:#"theKey"];
Load:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:#"theKey"];
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
The element in the array implements
#interface DictionaryItems : NSObject<NSCoding> {
NSString *value;
}
Then in the implementation of CommentItem, provides two methods:
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:value forKey:#"Value"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
self.value = [decoder decodeObjectForKey:#"Value"];
return self;
}
Hope it helps :)
When I try to use NSUserDefaults on two different screens, the NSUserDefaults does not apply and there is not an error that comes up. Basically, I want the next level to be available only after the first one is completed.
Here is my code:
View1:
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSInteger level1Complete = [prefs integerForKey:#"levelComplete"];
if (level1Complete == 11) {
button2.hidden = NO;
}
}
View2:
if (number11 == 5) {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setInteger:11 forKey:#"levelComplete"];
[prefs synchronize];
}
Please note: the game play itself is view2 and the level select is view1.
[[NSUserDefaults standardUserDefaults] setValue:#"11" forKey:#"levelComplete"];
if you can save it as a value and when you fetch it then convert it into integer.
All The Best!!