2012-07-17 38 views
2

我正在嘗試使用一個基本的父子對象繼承系統來編寫一個簡單的RPG,該系統被保存並加載到遊戲狀態,但是當加載發生時,沒有數據顯示父母,我努力理解爲什麼。如何使NSCoding與對象繼承一起工作?

爲了簡單起見,我已經做了簡單的親子對象繼承其中,從父Character

我把一切都在一個陣列(listOfPlayers

Player繼承然後歸檔對象;當我加載數據時,Character對象不再存在。

我已經登錄到控制檯以下;

METHOD: saveGameState() 
2012-07-17 20:12:24.762 TestState[72342:40b] self.listOfPlayers (1) 
2012-07-17 20:12:24.762 TestState[72342:40b] p.name = BOB 
2012-07-17 20:12:24.763 TestState[72342:40b] p.xp = 1000 

METHOD: loadGameState() 
2012-07-17 20:12:27.098 TestState[72342:40b] Last Save Date = 2012-07-17 19:12:24 +0000 
2012-07-17 20:12:27.099 TestState[72342:40b] self.listOfPlayers (1) 
2012-07-17 20:12:27.100 TestState[72342:40b] p.name = (null) 
2012-07-17 20:12:27.101 TestState[72342:40b] p.xp = 1000 
2012-07-17 20:12:27.102 TestState[72342:40b] State:Loaded 

的保存狀態似乎被保存名稱(Character模型的一部分),但是 那麼負載狀態似乎已經爲null

我不知道我在做什麼錯了名字。

我現在的代碼如下;

// Inside my app delegate 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    // Singleton 
    GameStateManager *state = [GameStateManager sharedGameStateManager]; 
    [state setupGameState]; 
    return YES; 
} 

// Character.h 
@interface Character : NSObject 
<NSCoding> 
{ 
    NSString *name; 
} 

@property (nonatomic, retain) NSString *name; 

@end 

// Character.m 
@implementation Character 
@synthesize name; 

#pragma mark - NSCoding 

-(id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super init]; 

    if (self) 
    { 
     NSLog(@"Loading character object"); 
     self.name = [aDecoder decodeObjectForKey:@"name"]; 
    } 

    return self; 
} 

-(void)encodeWithCoder:(NSCoder *)aCoder 
{  
    // Archive the object 
    NSLog(@"Archiving character object"); 

    [aCoder encodeObject:self.name forKey:@"name"]; 
} 
@end 


// Player.h 
#import "Character.h" 

@interface Player : Character 
<NSCoding> 
{ 
    NSNumber *xp; // xp points 
} 
@property (nonatomic, retain) NSNumber *xp; 

+(NSMutableArray *) createPlayers; 
@end 

// Player.m 
@implementation Player 
@synthesize xp; 

- (id)init { 
    self = [super init]; 
    if (self) { 
    } 
    return self; 
} 

+(NSMutableArray *) createPlayers 
{ 
    NSMutableArray *list = [NSMutableArray array]; 

    Player *p1 = [[Player alloc] init]; 
    [p1 setXp:[NSNumber numberWithInt:1000]]; 
    [p1 setName:@"BOB"]; 
    [list addObject:p1]; 
    [p1 release]; 

    return list; 
} 


#pragma mark - NSCoding 

-(id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super init]; 

    if (self) 
    { 
     self.xp = [aDecoder decodeObjectForKey:@"xp"]; 
    } 

    return self; 
} 

-(void)encodeWithCoder:(NSCoder *)aCoder 
{  
    // Archive the object 
    [aCoder encodeObject:self.xp forKey:@"xp"]; 
} 
@end 

// GameStateManager.m file  
-(void)saveGameState 
{ 
    NSLog(@"METHOD: saveGameState()"); 

    self.lastSaveDate = [NSDate date]; 

    NSLog(@"self.listOfPlayers (%d)", [self.listOfPlayers count]); 


    for (Player *p in self.listOfPlayers) { 
     NSLog(@"p.name = %@", p.name); 
     NSLog(@"p.xp = %d", [p.xp intValue]); 
    } 

    NSString *file = kGameSaveFile;  
    NSString *documentsDirectory = [MyHelpers getDocumentsDirectory]; 
    NSString *gameStatePath = [documentsDirectory stringByAppendingPathComponent:file]; 
    BOOL result; 

    NSLog(@"gameStatePath = %@", gameStatePath); 

    // Set up the encoder and storage for the game state data 
    NSMutableData *gameData; 
    NSKeyedArchiver *encoder; 
    gameData = [NSMutableData data]; 
    encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:gameData]; 

    // Archive the object 
    [encoder encodeObject:self.lastSaveDate forKey:@"lastSaveDate"]; 
    [encoder encodeObject:self.listOfPlayers forKey:@"listOfPlayers"]; 

    // Finish encoding and write to disk 
    [encoder finishEncoding]; 
    result = [gameData writeToFile:gameStatePath atomically:YES]; 
    [encoder release]; 

    if (result == YES) 
    { 
     NSLog(@"Result = OK"); 
    } else { 
     NSLog(@"Result = BAD"); 
    } 
} 

-(void)loadGameState 
{ 
    NSLog(@"METHOD: loadGameState()"); 

    NSString *file = kGameSaveFile; 
    NSString *documentsDirectory = [MyHelpers getDocumentsDirectory]; 
    NSString *gameStatePath = [documentsDirectory stringByAppendingPathComponent:file]; 


    NSMutableData *gameData; 
    NSKeyedUnarchiver *decoder;  
    gameData = [NSData dataWithContentsOfFile:gameStatePath]; 

    // Check to see if the .dat file exists, and load contents 
    if (gameData) 
    { 
     decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:gameData]; 

     self.lastSaveDate = [[decoder decodeObjectForKey:@"lastSaveDate"] retain]; 
     self.listOfPlayers = [[decoder decodeObjectForKey:@"listOfPlayers"] retain]; 

     [decoder finishDecoding]; 
     [decoder release]; 

     NSLog(@"Last Save Date = %@", self.lastSaveDate); 
     NSLog(@"self.listOfPlayers (%d)", [self.listOfPlayers count]); 


     for (Player *p in self.listOfPlayers) { 
      NSLog(@"p.name = %@", p.name); 
      NSLog(@"p.xp = %d", [p.xp intValue]); 
     } 

    } else { 

     NSLog(@"No game data!"); 
     assert(-1); 
     abort(); 

    } 


    NSLog(@"State:Loaded"); 
} 

編輯,

我認爲它必須有if ((self = [super initWithCoder:aDecoder]))[super encodeWithCoder:aCoder];

+0

我一直在尋找http://stackoverflow.com/questions/7904298/using-nscoding-on-a-subclass-of-custom-class?rq=1,似乎有一個工作答案,但我仍在測試它 – zardon 2012-07-17 19:42:53

回答

3

使用

if ((self = [super initWithCoder:aDecoder])) and [super encodeWithCoder:aCoder]; 

已經幫我解決這個問題,也該question有答案,這也有幫助。

感謝