samedi 27 juin 2015

Saving OS X Game Data Using NSData and NSMutableArrays

I am trying to store the hi-score of several levels in a NSMutableArray, which will then be saved in a file in the Documents folder. I know I can use plists, but I don't want the content to be modified by the user. It appears that NSMutableArray *hiscore is not being initialized and I'm not sure how to fix this. For primitives it seems fine, but for objects it's not working.

GameData.h

@interface GameData : NSObject <NSCoding>

@property (assign, nonatomic) int level;
@property (assign, nonatomic) NSMutableArray *hiscore;

+(instancetype)sharedGameData;
-(void)save;
-(void)reset;

@end

GameData.m

#import "GameData.h"

@implementation GameData

static NSString* const GameDataLevelKey = @"level";
static NSString* const GameDataHiscoreKey = @"hiscore";

- (instancetype)initWithCoder:(NSCoder *)decoder {
    self = [self init];
    if (self) {
        _level = [decoder decodeDoubleForKey: GameDataLevelKey];
        _hiscore = [decoder decodeObjectForKey:GameDataHiscoreKey];
    }
    return self;
}

+ (instancetype)sharedGameData {
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [self loadInstance];
    });

    return sharedInstance;
}

+(instancetype)loadInstance {
    NSData* decodedData = [NSData dataWithContentsOfFile: [GameData filePath]];
    if (decodedData) {
        GameData* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodedData];
        return gameData;
    }

    return [[GameData alloc] init];
}

-(void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeDouble:self.level forKey: GameDataLevelKey];
    [encoder encodeObject:self.hiscore forKey:GameDataHiscoreKey];
}

+(NSString*)filePath {
    static NSString* filePath = nil;
    if (!filePath) {
        filePath =
        [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
         stringByAppendingPathComponent:@"gamedata"];
    }
    return filePath;
}

-(void)save {
    NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self];
    [encodedData writeToFile:[GameData filePath] atomically:YES];
    /*[_hiscore writeToFile:[GameData filePath] atomically:YES];*/
}

-(void)reset {
    self.level = 0;
}

@end

LevelScene.m

#import "GameData.h"
...
[[[GameData sharedGameData] hiscore] addObject:@1500];
[[GameData sharedGameData] save];

Aucun commentaire:

Enregistrer un commentaire