Saving Users Scores - ios

Ola, I am trying to find a way to save user scores so when it is closed from the background it saves their scores and when open again it displays that score once again. By the way the thing Im saving is a tap counter so when they tap it has to add onto their previous score.
Any suggestions?

Save:
int numberOfTaps = 42; // some number of taps
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
[standardUserDefaults setValue:[NSNumber numberWithInt:numberOfTaps] forKey:#"numberOfTaps"];
Retrieve:
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
int savedTaps = [[standardUserDefaults objectForKey:#"numberOfTaps"] intValue];
Updating For Further Information
Just to make it extremely easy:
Copy these methods somewhere in your .m
- (void) saveNumberOfTaps:(int)numberOfTaps {
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:numberOfTaps] forKey:#"numberOfTaps"];
NSLog(#"Saved numberOfTaps: %i", numberOfTaps);
}
- (int) getNumberOfTaps {
if ([[[NSUserDefaults standardUserDefaults] objectForKey:#"numberOfTaps"] intValue]) {
int numberOfTaps = [[[NSUserDefaults standardUserDefaults] objectForKey:#"numberOfTaps"] intValue];
NSLog(#"Getting numberOfTaps: %i", numberOfTaps);
return numberOfTaps;
}
else {
NSLog(#"No taps saved yet");
return 0;
}
}
Then whenever you want to use these values, you can use the following:
// Save Taps
[self saveNumberOfTaps:14];
// Get Taps
int taps = [self getNumberOfTaps];
NSLog(#"taps retrieved: %i", taps);

It sounds like you're just starting out, so try using NSUserDefaults. Once you need something more advanced, look into Core Data.

Related

call different method with same string in different value

I have two methods in my .m file .And i want to access by different values but in my Facebook variable gives nil value but if i use only one line and remove second line of object for key then it work fine for one method .
How i do this which work for my both methods
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[[NSUserDefaults standardUserDefaults] synchronize];
user=[defaults objectForKey:#"userid"];
facebook=[defaults objectForKey:#"FACEBOOKprofile"];
facebook =[defaults objectForKey:#"VLCC"];
if ([facebook isEqualToString:#"VLCCFACEBOOK"])
{
[self FacebookRecord];
}
else if([facebook isEqualToString:#"VLCC"])
{
[self VlccRecord];
}
assume that
Choice-1
// for accessing the both condition in same time
Initially Store the UserDefault value based on your method.
if you are access with facebook , on that time store the string like
[[NSUserDefaults standardUserDefaults] setObject:"VLCCFACEBOOK" forKey:#"FACEBOOKprofile"];
[[NSUserDefaults standardUserDefaults] synchronize];
if you are access with VLCC , on that time store the string like
[[NSUserDefaults standardUserDefaults] setObject:"VLCC" forKey:#"VLCCprofile"];
[[NSUserDefaults standardUserDefaults] synchronize];
and retrieve the both and check like
if ([[[NSUserDefaults standardUserDefaults]
objectForKey:#"FACEBOOKprofile"]isEqualToString:#"VLCCFACEBOOK"])
{
[self FacebookRecord];
}
if([[[NSUserDefaults standardUserDefaults]
objectForKey:#"VLCCprofile"] isEqualToString:#"VLCC"])
{
[self VlccRecord];
}
Choice-2
// for accessing single condition on single time
if you are access with facebook , on that time store the string like
[[NSUserDefaults standardUserDefaults] setObject:"VLCCFACEBOOK" forKey:#"FACEBOOKprofile"];
[[NSUserDefaults standardUserDefaults] synchronize];
if you are access with VLCC , on that time store the string like
[[NSUserDefaults standardUserDefaults] setObject:"VLCC" forKey:#"FACEBOOKprofile"];
[[NSUserDefaults standardUserDefaults] synchronize];
and retrieve the both and check like
if ([[[NSUserDefaults standardUserDefaults]
objectForKey:#"FACEBOOKprofile"]isEqualToString:#"VLCCFACEBOOK"])
{
[self FacebookRecord];
}
else if([[[NSUserDefaults standardUserDefaults]
objectForKey:#"FACEBOOKprofile"] isEqualToString:#"VLCC"])
{
[self VlccRecord];
}
In your code, the [self VlccRecord] method will always get called because you are overwriting the facebook variable.
facebook=[defaults objectForKey:#"FACEBOOKprofile"];
facebook =[defaults objectForKey:#"VLCC"];
If you are looking to append the two strings : Then use the stringbyAppendingString method.
int a = 10;
a = 20;
print >> a; //20
int a = 10;
print1 >> a; //10
a = 20;
print2 >> a; //20
Here,
a = facebook;
print1 = [self FacebookRecord];
print2 = [self VlccRecord];
I believe you'll understand.

iOS - Retrieving and saving scores of a game

I developed a small game , , so I manage something like this , when app lunches for the first time , it save the very first record , then after that it loads and compares the new records with the the first time record . but the problem is when user hit the record it should be saved the new record but it doesn't !!! and saves the first record again ! here is my code :
- (void)manageScores {
NSLog(#"managed");
NSString *tempScore = [NSString stringWithFormat:#"%#",scoreLabel.text];
GO.scoreNumber = [tempScore integerValue];
GO.bestScoreNumber = [tempScore integerValue];
GO.scores.text = [NSString stringWithFormat:#"score:%d",GO.scoreNumber];
GO.bestScore.text = [NSString stringWithFormat:#"best:%d",GO.bestScoreNumber];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
// app already launched
NSLog(#"app already launched");
[GO loadBestScore];
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
// This is the first launch ever
NSLog(#"first time lunch ever");
[GO saveBestScore];
}
if (GO.scoreNumber > GO.bestScoreNumber) {
//**************THIS METHOD DOESN'T WORK WHEN USER HIT THE RECORD*********/////
[GO saveBestScore];
//**************//
GO.scores.text = [NSString stringWithFormat:#"score:%d",GO.scoreNumber];
GO.bestScore.text = [NSString stringWithFormat:#"best:%d",GO.scoreNumber];
GO.shareScore.text = [NSString stringWithFormat:#"score:%d",GO.bestScoreNumber];
NSLog(#"new record");
}
if (GO.scoreNumber < GO.bestScoreNumber) {
GO.scores.text = [NSString stringWithFormat:#"score:%d",GO.scoreNumber];
GO.bestScore.text = [NSString stringWithFormat:#"best:%d",GO.bestScoreNumber];
GO.shareScore.text = [NSString stringWithFormat:#"score:%d",GO.bestScoreNumber];
[GO loadBestScore];
NSLog(#"NO NEW RECORD");
}
}
saving and loading scores (methods form GameOver.h/m (GO) )
- (void)saveBestScore {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:bestScoreNumber forKey:#"highScore"];
[defaults synchronize];
NSLog(#"BEST SCORE SAVED:%i",bestScoreNumber);
}
- (void)loadBestScore {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
bestScoreNumber = (int)[prefs integerForKey:#"highScore"];
}
Looks like you should save scoreNumber rather than bestScoreNumber
Reason:
The following code wants to save the best score because GO.ScoreNumber > Go.BestScoreNumber.
if (GO.scoreNumber > GO.bestScoreNumber) {
//**************THIS METHOD DOESN'T WORK WHEN USER HIT THE RECORD*********/////
[GO saveBestScore];
//**************//
GO.scores.text = [NSString stringWithFormat:#"score:%d",GO.scoreNumber];
GO.bestScore.text = [NSString stringWithFormat:#"best:%d",GO.scoreNumber];
GO.shareScore.text = [NSString stringWithFormat:#"score:%d",GO.bestScoreNumber];
NSLog(#"new record");
}
But in saveBestScore, it stores bestScoreNumber, which is the previous highest score number.
[defaults setInteger:bestScoreNumber forKey:#"highScore"];
- (void)saveBestScore
This method doesn't take an argument, but it should.
If you're keeping scores as int, you should modify it to look like this:
- (void)saveBestScore:(int)bestScore
Then, on first launch, call saveBestScore with an argument of 0, just to get it initialize. In fact, if you write saveBestScore method correctly, you don't really need to check whether the app has already launched ever.
- (void)saveBestScore:(int)bestScore {
if (bestScore > [[[NSUserDefaults standardUserDefaults]
objectForKey:#"BestScore"] intValue]); {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber
numberWithInt:bestScore] forKey:#"BestScore"];
}
- (int)loadBestScore {
return [[[NSUserDefaults standardUserDefaults] objectForKey:#"BestScore]
intValue];
}

Method Called only After App Update

I have a Scenario , where i have to call a Method only once , whenever a User Will Update the Application or make a Fresh Install.
SO my Question is there is any particular Method to be called in App Delegate , After We update the Application , so if someone can tell me a another way to Achieve this , that would be really appreciated.
I would set a value in NSUserDefaults after you have called the function one time. See the accepted answer here: iOS : Call a method just one time
If you need to run after an update, you should include an always increasing number, or pull the build number, and check against the saved value. This will allow you to know if the app has been updated.
I am writing following function which uniquely checks if user has rated the current version, [self nowRate] is the function, please change this to whatever action you want to perform uniquely per version
-(void)rateApp {
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleShortVersionString"];
NSMutableDictionary*appRatedForVersion = [[NSMutableDictionary alloc] init];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([[[NSUserDefaults standardUserDefaults] dictionaryRepresentation].allKeys containsObject:#"AppRateDictionaryData"]){
NSData *versionRateData = [defaults objectForKey:#"AppRateDictionaryData"];
appRatedForVersion = [NSKeyedUnarchiver unarchiveObjectWithData:versionRateData];
if ([appRatedForVersion objectForKey:version] != nil) {
NSNumber *isAppRatedForCurrentVersion = [appRatedForVersion objectForKey:version];
BOOL hasBeenRated = [isAppRatedForCurrentVersion boolValue];
if (hasBeenRated) {
//Action already performed in this version do whatever you like
} else {
[self nowRate];
}
} else {
[appRatedForVersion setObject:[NSNumber numberWithBool:YES] forKey:version];
NSData *versionRateData1 = [NSKeyedArchiver archivedDataWithRootObject:appRatedForVersion];
[defaults setObject:versionRateData1 forKey:#"AppRateDictionaryData"];
[defaults synchronize];
[self nowRate];
}
} else {
[appRatedForVersion setObject:[NSNumber numberWithBool:YES] forKey:version];
NSData *versionRateData = [NSKeyedArchiver archivedDataWithRootObject:appRatedForVersion];
[defaults setObject:versionRateData forKey:#"AppRateDictionaryData"];
[defaults synchronize];
[self nowRate];
}
}

`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