iphone - NSCoderを使用して静的シングルトンオブジェクトを初期化する

iphone objective-c singleton nskeyedarchiver initwithcoder

私はiPhoneアプリで作業していて、共有シングルトンクラスでいくつかの問題に直面しています。
共有シングルトンを使用して2つの変数を格納しています
int gameRunsおよびint 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つのメソッドinitWithCoderencodeWithCoderを追加しました。

- (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を実行するたびに新しいオブジェクトを割り当てずに、同じオブジェクトへの参照を取得する最良の方法を知る必要があるだけです。

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

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


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

iphone - drawRectの伸縮可能な画像が原因でスクロールが遅くなる

iphone - Parsekit:個々の引用文字を一致させる方法は?

iphone - iPhone-低メモリ状態に対処する方法

iphone - プログラムでキーボードを閉じるにはどうすればよいですか?

iphone - デバイスがxcodeオーガナイザーウィンドウで認識されない

iphone - シーケンシャルUIView変換

iphone - UITextFieldsにテキストが追加されたときに、UIReturnKeyGoとUIReturnKeyNextを切り替えるにはどうすればよいですか?

c# - UITableViewでランダムに「NIBをバンドルでロードできませんでした」

iphone - PrintScreenを使用したり、画面の一部に画像を保存したりできますか?

iphone - プロパティtxtname(uiTextView *)のタイプがivar txtname(uiTextView)と一致しません