2012-07-17 42 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有答案,这也有帮助。

感谢