2014-10-05 33 views
0

我正在創建一個應用程序,需要存儲來自多個不同級別的高分。我正在使用http://www.raywenderlich.com/63235/how-to-save-your-game-data-tutorial-part-1-of-2上的優秀教程作爲我正在嘗試做的事情的基礎。按照他們的建議我使用https://gist.github.com/dhoerl/1170641用SpriteKit和iOS保存高分7

在我的iOS SIM出來的Xcode的keychainwrapper,在遊戲狀態保存工作完全正常,我可以關閉的Xcode,甚至重新啓動我的Mac和喜歡它應該高分出現。但是,當我使用我的iPhone 5作爲目的地時,它根本不起作用。如果我殺了應用程序,高分就會消失。不知道我在這筆交易中缺少什麼。

這裏是我的gameState.h:

#import <Foundation/Foundation.h> 

@interface GameState : NSObject <NSCoding> 

@property (assign, nonatomic) long score; 
@property (assign, nonatomic) long highScoreL1; 
@property (assign, nonatomic) long highScoreL2; 
@property (nonatomic) long levelIndex; 
@property (nonatomic) long lvlIndexMax; 

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

@end 

這是我的gameState.m

#import "GameState.h" 
#import "KeychainWrapper.h" 

@implementation GameState 

static NSString* const SSGameDataChecksumKey = @"SSGameDataChecksumKey"; 
static NSString* const SSGameDataHighScoreL1Key = @"highScoreL1"; 
static NSString* const SSGameDataHighScoreL2Key = @"highScoreL2"; 

-(void)encodeWithCoder:(NSCoder *)encoder { 
[encoder encodeDouble:self.highScoreL1 forKey:SSGameDataHighScoreL1Key]; 
[encoder encodeDouble:self.highScoreL2 forKey:SSGameDataHighScoreL2Key]; 
} 

-(instancetype)initWithCoder:(NSCoder *)decoder { 
self = [self init]; 
if (self) { 
    _highScoreL1 = [decoder decodeDoubleForKey:SSGameDataHighScoreL1Key]; 
    _highScoreL2 = [decoder decodeDoubleForKey:SSGameDataHighScoreL2Key]; 
} 

return self; 
} 

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

return filePath; 
} 

+(instancetype)loadInstance { 
NSData* decodedData = [NSData dataWithContentsOfFile: [GameState filePath]]; 
if (decodedData) { 
    NSString* checksumOfSavedFile = [KeychainWrapper computeSHA256DigestForData:decodedData]; 
    NSString* checksumInKeychain = [KeychainWrapper keychainStringFromMatchingIdentifier:SSGameDataChecksumKey]; 

    if ([checksumOfSavedFile isEqualToString: checksumInKeychain]){ 
     GameState* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodedData]; 
     return gameData; 
    } 
} 

return [[GameState alloc]init]; 
} 

-(void)save { 
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self]; 
[encodedData writeToFile:[GameState filePath] atomically:YES]; 
NSString* checksum = [KeychainWrapper computeSHA256DigestForData: encodedData]; 
if ([KeychainWrapper keychainStringFromMatchingIdentifier:SSGameDataChecksumKey]) { 
    [KeychainWrapper updateKeychainValue:checksum forIdentifier:SSGameDataChecksumKey]; 
} else { 
    [KeychainWrapper createKeychainValue:checksum forIdentifier:SSGameDataChecksumKey]; 
} 
} 

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

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

return sharedInstance; 
} 

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

-(void)resetAll { 
self.score = 0; 
//self.highScoreL1 = 0; 
//self.highScoreL2 = 0; 
} 

@end 

裏面我跟蹤分數每個級別,那麼當用戶丟失了比賽,我用下面的行在去遊戲結束場景之前更新高分:

[GameState sharedGameData].highScoreL1 = MAX([GameState sharedGameData].score, [GameState sharedGameData].highScoreL1); 

最後,在Game Over ,我用

[[GameState sharedGameData] save]; 

保存高分。

預先感謝您的幫助,任何方向都是非常棒的。讓我知道你是否需要更多信息!

+0

保存本地分數最安全的方法是使用NSUserDefaults的例如 - (void)setTopscore :(long long)newScore { NSString * newhighScore = [NSString stringWithFormat:@「%lld」,(long long)newScore]; [_userlocalData setObject:newhighScore forKey:topScore]; [_userlocalData synchronize]; } //從本地數據存儲中獲得最高分====================================== ============================== // - (NSString *)getTopscore { NSString * newhighScore = [_userlocalData stringForKey:最高得分]; return newhighScore; } – dragoneye 2014-10-06 05:57:34

回答

0

在不同場景之間保存本地數據的最安全和最快捷的方法是使用nsuserdefaults例如

//靜態變量

static NSString * topScore= @"topScore"; 




-(void)setTopscore:(long long)newScore 
{ 

    NSString *newhighScore = [NSString stringWithFormat:@"%lld", (long long)newScore]; 

    [_userlocalData setObject:newhighScore forKey:topScore]; 
    [_userlocalData synchronize]; 
} 


//get top score from local database storage====================================================================// 
-(NSString*)getTopscore 
{ 
    NSString *newhighScore = [_userlocalData stringForKey:topScore]; 
    return newhighScore; 
} 

我想這和它沒有任何問題工作的所有iOS設備上和Mac本身

+0

Gotcha。這絕對是有道理的,但我一直都認爲使用NSUserDefaults是非常不安全的,並且非常容易被破解。 – 2014-10-06 22:51:50

+0

此外,iCloud和GameCenter同步將是一個優點。我想我可以拉NSUserDefault信息,並在必要時發送。思考? – 2014-10-06 22:53:18

+0

同意u nsuserdefault是不安全且容易入侵的,但如果您正在尋找最安全的方式來保存數據,那麼使用遊戲是節省時間的過程。 – dragoneye 2014-10-07 05:08:14