11


Apple の iOSTableViewとセルの再利用は私を殺しています。検索して検索して勉強しましたが、良いドキュメントや良い答えが見つかりません。問題は、TableViewセルを再利用すると、選択したセルに設定されたチェックマーク (セル アクセサリ) のようなものが、テーブル ビューのさらに下のセルで繰り返されることです。メモリの制約により、セルの再利用が設計によるものであることは理解していますが、たとえば50個のアイテムを含むリストがあり、不要な場所に追加のチェックマークを設定し始めると、全体の努力が無駄になります.

やりたいことは、選択したセルにチェックマークを設定することだけです。私は独自のカスタム セル クラスと、ボイラー プレートの TableView クラスによって生成された標準セルを使用してこれを試しましたが、結果は常に同じです。

Apple には、開発センターからダウンロードできる TouchCell というサンプル プロジェクトもあります。これは、左側にイメージ コントロールがあるカスタム セルを使用してチェックマークを設定する別の方法を示すはずです。このプロジェクトでは、変更可能な配列の代わりにデータ ソースにディクショナリ オブジェクトを使用するため、各項目には文字列値とブール チェック値があります。この bool checked 値は、選択した項目を追跡できるようにチェックマークを設定することになっています。このサンプル プロジェクトでは、TableView に 15 個以上のセルを入力するとすぐに、この間抜けな動作も表示されます。セルを再利用すると、不要なチェック マークが設定され始めます。

各セルに真に一意のセル識別子を使用して実験してみました。各セルが @"Acell" のようなものを持つ代わりに、静的な int を使用し、文字列にキャストして、セルが @"cell1"、@"cell2" などになるようにしました。テーブルに 30 項目しかない場合でも、スクロール中に生成されます。

チェックマークの繰り返しの問題は修正されましたが、メモリ使用量が高すぎると思われます。

これは、現在テーブルの表示可能領域にないセルが、スクロールして表示に戻ると、もう一度作成されるかのようです。

この苛立たしい動作に対するエレガントな解決策を思いついた人はいますか?

4

1 に答える 1

17

セルの再利用は難しい場合がありますが、次の 2 つの点に注意する必要があります。

  • 1 つのタイプのセルに 1の識別子を使用する - 複数の識別子を使用する必要があるのは、1 つのテーブル ビューで異なる UITableViewCell サブクラスを使用し、セルごとに異なる動作に依存する必要がある場合のみです。
  • 再利用するセルはどのような状態でもかまいません。つまり、セルのすべての側面を再度構成する必要があります。特に、checkmars/images/text/accessoryViews/accessoryTypes などです。

あなたがする必要があるのは、チェックマークの状態のためのストレージを作成することです.boolsを含む単純な配列(またはそれぞれboolean NSNumberオブジェクトを含むNSArray)がそれを行う必要があります。次に、セルを作成/再利用する必要がある場合は、次のロジックを使用します。

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *reuseIdentifier = @"MyCellType";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    if(cell == nil) {
        /* create cell here */
    }
    // Configure cell now
    cell.textLabel.text = @"Cell text"; // load from datasource
    if([[stateArray objectAtIndex:indexPath.row] boolValue]) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    return cell;
}

次に、タップで反応する必要があります。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:![[stateArray objectAtIndex:indexPath.row] boolValue]]];
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}

NSMutableArrayデータストアに使用することを忘れないでください;)

于 2011-06-11T14:32:20.037 に答える