Question

So this is my first time trying to save data in an iOS app. I've pieced together this code from various answers on this site in order to save a high score for a game I'm making. I created a plist named saves.plist (in my Supporting Files folder) and added a row of key @"bestScore" and type Number. The test log returns that the save is successful, and everything works; however, when I go to look at the plist after, nothing seems to have changed (the value of bestScore is 0). Am I saving to a different plist that is automatically created in my code? If this is the case, what is the point of being able to create plists in Xcode, and what is the best practice to use here as far as where/how to create/store/access plists?

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.fm = [NSFileManager defaultManager];

    self.destPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];//Documents directory
    self.destPath = [self.destPath stringByAppendingPathComponent:@"saves.plist"];

    // If the file doesn't exist in the Documents Folder, copy it.
    if (![self.fm fileExistsAtPath:self.destPath]) {
        NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"saves" ofType:@"plist"];
        [self.fm copyItemAtPath:sourcePath toPath:self.destPath error:nil];
    }
}

- (void)saveBestScore{
    NSNumber *bestScoreBox = [NSNumber numberWithUnsignedLong:self.bestScore];
    NSDictionary *data = @{bestScoreBox: @"bestScore"};

    BOOL successful = [data writeToFile:self.destPath atomically:YES];
    successful ? NSLog(@"YES") : NSLog(@"NO");
}
Was it helpful?

Solution

When you say

when I go to look at the plist after, nothing seems to have changed (the value of bestScore is 0)

Do you mean looking at the plist in xcode project files ? You have copied the plist into a device directory and therefore you wont be able to see the change in xcode.

If you are using simulator, you can access the changed plist at:

~/Library/Application Support/iPhone Simulator/<Simulator Version>/Applications/<application>/Documents/

One easy way of storing score is to use NSUserDefault, which is a dictionary like persistence store for each application.

Set Score:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:@(score) 
                 forKey:@"score"];
[userDefaults synchronize];

Get Score:

int score = [[[NSUserDefaults standardUserDefaults] objectForKey:@"score"] intValue];

UPDATE:

rmaddy mentioned NSUserDefaults supports setInteger:forKey and integerForKey: Therefore you dont need to wrap the score into a NSNumber

OTHER TIPS

When you write an NSDictionary to a plist using writeToFile:, the keys and values in the dictionary must follow strict rules. All keys must be NSString objects and all values must be property values (NSString, NSNumber, NSDate, NSData, etc.).

The problem you have is your dictionary has a key that is an NSNumber, not an NSString.

It appears you actually create the dictionary incorrectly. The syntax is:

@{ key : value, key : value, ... }

Change your code to:

NSDictionary *data = @{ @"bestScore" : bestScoreBox }; // key : value

Side note - your last line should be:

NSLog(@"%@", successful ? @"YES" : @"NO");

It's not good practice to use the ternary operator to run two different commands. It's meant to return one of two values.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top