I have a problem. There is class to store game progress:
struct GameData {
PackData & packDataById(LEVEL_PACK packId);
int gameVersion;
AudioData audio;
PackData sunrise;
PackData monochrome;
PackData nature;
};
//singleton
@interface GameDataObject : NSObject <NSCoding>
{
GameData data_;
}
+(GameDataObject*) sharedObject;
-(id) initForFirstLaunch;
-(GameData*) data;
-(void) save;
@end
and implementation:
@implementation GameDataObject
static GameDataObject *_sharedDataObject = nil;
+ (GameDataObject*) sharedObject
{
if (!_sharedDataObject) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *encodedObject = [defaults objectForKey:Key];
if (!encodedObject) {
_sharedDataObject = [[GameDataObject alloc] initForFirstLaunch];
}
else {
_sharedDataObject = (GameDataObject*)[NSKeyedUnarchiver unarchiveObjectWithData: encodedObject];
}
}
return _sharedDataObject;
}
-(GameData*) data
{
return &data_;
}
-(id) initForFirstLaunch
{
self = [super init];
if (self) {
data_.audio.reset();
data_.sunrise.reset();
data_.monochrome.reset();
data_.nature.reset();
data_.gameVersion = 1;
data_.sunrise.levelData[0].state = LEVEL_OPENED;
}
return self;
}
-(void) save
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSKeyedArchiver archivedDataWithRootObject:self] forKey:Key];
[defaults synchronize];
}
-(void) encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeInt:data_.gameVersion forKey:@"game-version"];
[encoder encodeBytes:(uint8_t*)&data_.audio length:sizeof(AudioData) forKey:@"audio-data"];
[encoder encodeBytes:(uint8_t*)&data_.sunrise length:sizeof(PackData) forKey:@"sunrise-pack"];
[encoder encodeBytes:(uint8_t*)&data_.monochrome length:sizeof(PackData) forKey:@"monochrome-pack"];
[encoder encodeBytes:(uint8_t*)&data_.nature length:sizeof(PackData) forKey:@"nature-pack"];
}
-(id) initWithCoder:(NSCoder *)decoder
{
self = [super init];
if (self) {
data_.gameVersion = [decoder decodeIntForKey:@"game-version"];
NSUInteger length = 0;
{
const uint8_t *buffer = [decoder decodeBytesForKey:@"audio-data" returnedLength:&length];
assert(length);
memcpy(&data_.audio, buffer, length);
}
{
const uint8_t *buffer = [decoder decodeBytesForKey:@"sunrise-pack" returnedLength:&length];
assert(length);
memcpy(&data_.sunrise, buffer, length);
}
{
const uint8_t *buffer = [decoder decodeBytesForKey:@"monochrome-pack" returnedLength:&length];
assert(length);
memcpy(&data_.monochrome, buffer, length);
}
{
const uint8_t *buffer = [decoder decodeBytesForKey:@"nature-pack" returnedLength:&length];
assert(length);
memcpy(&data_.nature, buffer, length);
}
}
return self;
}
@end
It loads and saves itself correctly when save is called directly after initialization and nothing more is done.
But when I try a simple thing. I write in appDidFinishLaunching
GameDataObject *obj = [GameDataObject sharedObject];
Then everything is done - just one simple menu is loaded, and I minimize the application so
-(void) applicationDidEnterBackground:(UIApplication*)application
{
[[CCDirector sharedDirector] stopAnimation];
[[GameDataObject sharedObject] save];
}
is executed. And in this method obj
is totally corrupted (before saving), sometimes it's even seen with debugger as another class object.
What am I doing wrong?
EDIT
Just launching the app and minimizing it causes the same problem.