2

私はiPhoneアプリに取り組んでおり、共有シングルトンクラスでいくつかの問題に直面しています。共有シングルトンを使用して2つの変数を格納して int gameRunsint totalScore ますが、「gamRuns」はユーザーがアプリを読み込むたびに増分するだけで、「totalScore」は明らかです:D

問題は次のとおりです。アプリがこのコードを使用して読み込まれるときに、独自のメソッドを使用してシングルトンと初期化を読み込みます。

+ (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プロトコルを追加し、次の2つのメソッド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ステートメントの最後の行が完全に機能し、期待どおりにアプリをロードするたびにインクリメントされ、本当に嬉しいです(笑)。

ただし、次のようにして別のクラスのシングルトンの参照を取得しようとすると、問題が発生します。

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

それは常に1にカウントバックしますが、何が起こるかはわかっていますが、それを解決するための最良の方法を訴えることはできませんinitWithCoder。シングルトンの場合、静的オブジェクトを返さず、新しいオブジェクトを作成しsharedLevelStateInstanceます。私の最初のカスタムメソッドで、ハードコードされたデフォルトに初期化します。

StackOverflow、助けてくれませんか?!

毎回新しいオブジェクトを割り当てることなく、同じオブジェクトへの参照を取得するための最良の方法を知る必要がありますinitWithCoder

ありがとう :)

4

1 に答える 1

2

したがって、コードはおそらく次のようになります。

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

シングルトンの変数を設定し、シングルトンを返します。シングルトンを保持して、NSCoderこのインスタンスをリリースしたときにシングルトンの割り当てが完全に解除されないようにしてください。

于 2012-01-22T19:07:35.563 に答える