У меня проблема. Есть класс для хранения прогресса игры:
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
и реализация:
@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
Он загружается и сохраняет себя правильно, когда save вызывается сразу после инициализации, и больше ничего не делается.
Но когда я попробую простую вещь. Я пишу в appDidFinishLaunching
GameDataObject *obj = [GameDataObject sharedObject];
Тогда все сделано - загружается только одно простое меню, и я минимизирую приложение, поэтому
-(void) applicationDidEnterBackground:(UIApplication*)application
{
[[CCDirector sharedDirector] stopAnimation];
[[GameDataObject sharedObject] save];
}
выполнено. И в этом методе obj
полностью поврежден (перед сохранением), иногда он даже рассматривается с отладчиком как другой объект класса.
Что я делаю не так?
EDIT
Та же проблема возникает при запуске приложения и его сворачивании.