Reputation: 2920
I am attempting to write a simple RPG using a basic Parent Child object inheritance system which is saved and loaded into Game State, however when loading occurs no data appears for the parent and I'm struggling to understand why.
For simplicity sake, I have made a simple Parent-child object inheritance where,
Player
inherits from the parent Character
I put everything in an array (listOfPlayers
) and then archive the objects; when I come to load the data, the Character
object is no longer there.
I have logged to the console the following;
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
The save state seems to be saving the name (part of the Character
model) but
then the load state seems to have the name as null
I am not sure what I am doing wrong.
My code now follows;
// 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");
}
Edit,
I think it has to have if ( (self = [super initWithCoder:aDecoder]) )
and [super encodeWithCoder:aCoder];
Upvotes: 2
Views: 851