0

私は楽しい小さなiPhoneアプリでかなりの仕事をしてきました。ある時点で、Persistantストアから多数のプレーヤーオブジェクトを取得し、それらを画面に表示します。新しいプレーヤーオブジェクト(カスタムUIButtonのみ)を追加したり、選択したプレーヤーを削除したりするオプションもあります。

ただし、どの「プレーヤー」が表示されているかをアプリが保存していないという点で、メモリ管理の問題が発生していると思います。

例:4人のプレーヤーが表示されているので、それらをすべて選択してから、すべて削除します。それらはすべて消えます。しかし、アプリケーションを終了してから再度開くと、それらはすべて再び存在します。彼らが去ったことがないかのように。したがって、私のコードのどこかで、それらは「実際に」削除されていません。

MagicApp201AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    context = [appDelegate managedObjectContext];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *desc = [NSEntityDescription entityForName:@"Player" inManagedObjectContext:context];
    [request setEntity:desc];
    NSError *error;
    NSMutableArray *objects = [[[context executeFetchRequest:request error:&error] mutableCopy] autorelease];
    if (objects == nil) {
        NSLog(@"Shit man, there was an error taking out the single player object when the view did load. ", error);
    }
    int j = 0;
    while (j < [objects count]) {
        if ([[[objects objectAtIndex:j] valueForKey:@"currentMultiPlayer"] boolValue] == NO) {
            [objects removeObjectAtIndex:j];
            j--;
        }
        else {
            j++;
        }
    }
    [self setPlayers:objects]; //This is a must, it NEEDS to work Objects are all the players playing

したがって、このスニピット(viewdidLoadメソッド内)では、永続ストアからプレーヤーを取得し、不要なオブジェクト(boolValueがNOのオブジェクト)を削除して、残りを保持します。これはうまくいきます、私はかなり確信しています。問題は、プレイヤーをどこから削除するかだと思います。そのコードは次のとおりです。

NSLog(@"Remove players");
/**
 For each selected player:
 Unselect them (remove them from SelectedPlayers)
 Remove the button from the view
 Remove the button object from the array
 Remove the player from Players
 */
NSLog(@"Debugging Removal: %d", [selectedPlayers count]);
for (int i=0; i < [selectedPlayers count]; i++) {
    NSManagedObject *rPlayer = [selectedPlayers objectAtIndex:i];

    [rPlayer setValue:[NSNumber numberWithBool:NO] forKey:@"currentMultiPlayer"];


    int index = [players indexOfObjectIdenticalTo:rPlayer]; //this is the index we need

    for (int j = (index + 1); j < [players count]; j++) {
        UIButton *tempButton = [playerButtons objectAtIndex:j];
        tempButton.tag--;
    }

    NSError *error;
    if ([context hasChanges] && ![context save:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    } 


    UIButton *aButton = [playerButtons objectAtIndex:index];

    [players removeObjectAtIndex:index];

    [aButton removeFromSuperview];

    [playerButtons removeObjectAtIndex:index];

}
[selectedPlayers removeAllObjects];

NSError *error;
if ([context hasChanges] && ![context save:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
} 


NSLog(@"About to refresh YES");
[self refreshAllPlayers:YES];

2番目のコードスニペットの大きな部分は、currentMultiPlayerに対してNOに設定したことです。いいえいいえいいえいいえいいえ、ビューが読み込まれたときに戻ってはいけません。私がそう言うまでは。コードの他の関連部分でYESに設定されているものはありません。それは私に考えさせます...おそらく彼らは救われていません。おそらくそれは保存されません、おそらくそれらのオブジェクトはもう管理されていないので、それらは保存されません。NSManagedオブジェクトの存続期間(比喩的に)はありますか?Players配列は、「viewDidLoad」メソッドで設定したものと同じであり、SelectedPlayersは、選択されたプレーヤー、NSManagedObjectsへの参照を保持します。アレイからそれらを削除することと関係がありますか?私はとても混乱しているので、いくつかの洞察をいただければ幸いです!!

4

2 に答える 2

0

さまざまな内部配列からプレーヤーオブジェクトを削除しているように見えますが、NSManagedObjectContextそれ自体からは削除していません。

于 2010-06-07T20:33:43.847 に答える
0

さらに多くのデバッグを行った後(かなり)、問題が見つかりました。最初のプレーヤー、またはスロット0のプレーヤーを「削除」するまで、コードは正常に機能しました。プレーヤーがフィルター処理されるタイミングを確認しました。

while (j < [objects count]) {
        if ([[[objects objectAtIndex:j] valueForKey:@"currentMultiPlayer"] boolValue] == NO) {
            [objects removeObjectAtIndex:j];
            j--;
        }
        else {
            j++;
        }
    }

そして、最初のプレーヤーがプレイしていない場合、jは-1になり、ループから抜け出し、残りのプレーヤーの検証に失敗し、奇妙なバグによってすべてのプレーヤーがゲームに戻されることに気付きました。メモリ管理とはまったく関係ありませんでしたが、バグを見つけるためにいくつかのリークを修正しました。ありがとうございました!

于 2010-06-08T13:40:53.670 に答える