Инициализация статического одноэлементного объекта с помощью NSCoder - PullRequest
2 голосов
/ 22 января 2012

Я работаю над приложением для iPhone и сталкиваюсь с некоторыми проблемами с моим общим синглтон-классом. Я использую общий синглтон для хранения двух переменных int gameRuns и int totalScore «gamRuns» просто увеличивается каждый раз, когда пользователь загружает приложение, и «totalScore» очевиден: D

проблема заключается в следующем, я загружаю синглтон и init, используя свой собственный метод, когда приложение загружается с использованием этого кода:

+ (SingletonLevelState*)sharedLevelStateInstance {

static SingletonLevelState *sharedLevelStateInstance;

@synchronized(self) {
    if(!sharedLevelStateInstance) {
        //Init a singleton
        sharedLevelStateInstance = [[SingletonLevelState alloc] init];
        sharedLevelStateInstance->gameRuns = 1;
        sharedLevelStateInstance->totalScore = 0;
    }
}
return sharedLevelStateInstance;
}

Это прекрасно работает, так как я могу ссылаться на этот класс из любого другого класса и всегда получать указатель на тот же объект, поэтому он отлично работает и из других объектов:

sharedLevelState = [SingletonLevelState sharedLevelStateInstance];
sharedLevelStateInstance.gameRuns++;

Теперь я добавил протокол NSCoder и добавил два метода initWithCoder и encodeWithCoder следующим образом:

- (void) encodeWithCoder: (NSCoder *)coder
{
    //encode level data
    [coder encodeInt:self->gameRuns forKey:@"gameRuns"];
    [coder encodeInt:self->totalScore forKey:@"totalScore"];
}
- (id) initWithCoder: (NSCoder *) coder
{
    if(self = [super init]){
        self->gameRuns = [coder decodeIntForKey:@"gameRuns"];
        self->totalScore = [coder decodeIntForKey:@"totalScore"];
    }
    return self;
}

Теперь, когда приложение загружается, я проверяю, есть ли у нас уже сохраненное состояние, если оно существует, я просто разархивирую класс с этим файлом, если нет, я инициирую этот класс, используя мой пользовательский метод выше, а затем устанавливаю его по умолчанию, закодируйте его в файл, чтобы у нас было сохраненное состояние, вот код:

 //Load Level state
sharedLevelStateInstance = [SingletonLevelState sharedLevelStateInstance];

//Check if file is saved
NSFileManager *fm = [[NSFileManager alloc] init];
NSString *gameStatePath = [NSString stringWithString:[self getSavePath]];

if([fm fileExistsAtPath:gameStatePath]){
    [self loadState];
    sharedLevelStateInstance.gameRuns = sharedLevelStateInstance.gameRuns+1;
    NSLog(@"Loaded %d times", [sharedLevelStateInstance gameRuns]);
}
[fm release];

Теперь последняя строка в операторе if работает отлично, она увеличивается каждый раз, когда я загружаю приложение, как ожидалось, и Я чувствую себя действительно счастливым lol.

Однако проблема возникает , когда я пытаюсь получить ссылку на синглтон в другом классе, выполнив следующее:

sharedLevelStateInstance = [SingletonLevelState sharedLevelStateInstance];
NSLog(@"Played: %d times", sharedLevelStateInstance.gameRuns);

Это всегда отсчитывает до 1, я знаю, что происходит, но я не знаю, каков наилучший способ решить это, когда я initWithCoder синглтон, Он не возвращает статический объект, он создает новый, когда Я инициализирую свой sharedLevelStateInstance, он вызывает мой первый пользовательский метод, инициализируя его жестко заданными значениями по умолчанию.

Итак, StackOverflow, не могли бы вы мне помочь?!

Мне просто нужно знать, как лучше всего получить ссылку на один и тот же объект без выделения нового каждый раз, когда я initWithCoder!

Спасибо:)

1 Ответ

2 голосов
/ 22 января 2012

Итак, ваш код, вероятно, должен выглядеть следующим образом:

if(self = [[SingletonLevelState sharedLevelStateInstance] retain])

, который устанавливает переменные синглтона и возвращает синглтон.Обязательно сохраните синглтон, чтобы, когда NSCoder выпустит этот экземпляр, он не полностью освободил ваш синглтон.

...