1

最初に UITableViewCell がこのように再利用のために登録されます

UINib *cellLoader=[UINib nibWithNibName:@"GroupCell_iPhone" bundle:nil];
[self.tableView registerNib:cellLoader forCellReuseIdentifier:@"GroupCell"];

次に cellForRowAtIndexPath デリゲートで

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

セルがデキューされる

GroupCell_iPhone *cell=(GroupCell_iPhone*)[self.tableView dequeueReusableCellWithIdentifier:@"GroupCell"];

次に、一連のUILabelおよびその他のオブジェクトが一連の基準に基づいて動的に作成され、このようにセルに追加されます

[cell.contentView addSubview:noActivityLabel];

この問題は、2 番目以降のセルがキューから取り出され、最初にキューから取り出されたセルから動的に追加されたオブジェクトを持っているように見える場合に発生します。最終的に、すべての細胞は異なります。キューから取り出されたセルは、UITableViewCell の 1 つのインスタンスへの「ポインタ」ですか? これらの後でデキューされたセルに、最初のコンテンツが含まれるのはなぜですか?

この場合、動的/変化するコンテンツを含むセルを作成するための最良のアプローチは何ですか? セルの新しいインスタンスを毎回作成する必要がありますか? デキューされたセルを「複製」できますか?

明確化: テーブル内のすべてのセルは基本レイアウトで始まりますが、そのセルに関連付けられたデータに基づいて、一意のコンテンツが各セルに追加されます。したがって、テーブル内のすべてのセルは一意です。つまり、セルにはさまざまなサブビュー (UILable、UIImageView など) があります。

4

2 に答える 2

0

それが最善の方法かどうかはわかりませんが、次のことを行いました。

CustomCellType1、CustomCellType2、Custom CellType3 など、いくつかのサブクラスを持つ CustomCellClass を作成しました。ここで、CustomCellSubclasses はすべて同じモデルの異なる部分を使用して情報を表示します。

次に、いくつかの基本的な属性を設定する prePareDataForCell 関数を CustomCellClass に追加します。CustomCellSubclass がそれらを必要とする場合はそれらを持っていますが、そうでない場合は同じように動きます (これは良い習慣であるかどうかわからない部分だと思います)。

次に、次のような擬似コードを実行できます。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomCellClass *returnCell = (CustomCellClass*)[tableView cellForRowAtIndexPath:indexPath];
    MyObject *obj = [self.fetchedResultsController objectAtIndexPath:indexPath];

    if ([returnCell.reuseIdentifier isEqualToString:CustomCellType1) {
        CustomCellType1 *cell = (CustomCellType1*)[tableView dequeueReusableCellWithIdentifier:CustomCellType1];

        if (!cell) {
            cell = [[CustomCellType1 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CustomCellType1];
            NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCellType1" owner:self options:nil];
            cell = [topLevelObjects objectAtIndex:0];
        }
        // This is a basic cell doesn't need anything special done with the object model
        returnCell = cell;
    } else if ([[returnCell reuseIdentifier] isEqualToString:CustomCellType2]) {
        CustomCellType2 *cell = (CustomCellType2 *)[tableView dequeueReusableCellWithIdentifier:CustomCellType2];

        if (!cell) {
            cell = [[CustomCellType2 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CustomCellType2];
            NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCellType2" owner:self options:nil];
            cell = [topLevelObjects objectAtIndex:0];
        }
        // Do stuff with obj data only needed for this type of cell, perhaps modify the cells subviews
        [cell preConfigureCustomCellType2:obj];
        returnCell = cell;
    } else {
        CustomCellType3 *cell = (CustomCellType3*)[tableView dequeueReusableCellWithIdentifier:StandardMailCell];

        if (!cell) {
            cell = [[CustomCellType3 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:StandardMailCell];
            NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCellType3" owner:self options:nil];
            cell = [topLevelObjects objectAtIndex:0];
        }
        // Do stuff with obj data only needed for this type of cell perhaps modify the same subviews in a different way for this type of cell
        [cell preConfigureCustomCellType3:mail];
        returnCell = cell;
    }

    if (![tableView isDragging] && !tableView.decelerating) {
             // I used this to only run an expensive operation after the the customer flicks and the table comes to a rest.
    }

    return returnCell;
}
于 2012-10-30T07:42:24.483 に答える
0

これらの後でデキューされたセルに、最初のコンテンツが含まれるのはなぜですか?

新しいセルを毎回再作成するのではなく、既に作成されて表示されなくなったセルを再利用する方がはるかに優れています。これは、セルをデキューするときに tableView が実際に行うことです。可能であれば、表示されていないセルがいくつか表示されます。

1000 個のセルを含む tableview を表示する必要があるとします。tableView は実際には一度に 6 個のセルしか表示していません。1000 個のセルを作成する代わりに、セル スタックを再利用するため、新しいセルを再作成する必要はありません。

キューから取り出されたセルは、UITableViewCell の 1 つのインスタンスへの「ポインタ」ですか? これらの後でデキューされたセルに、最初のコンテンツが含まれるのはなぜですか?

同じポインター オブジェクトなので、最初に表示されたときと同じ内容になります。次に、そのデータを更新する必要があります。

セルの新しいインスタンスを毎回作成する必要がありますか? デキューされたセルを「複製」できますか?

次の場合にのみ、新しいセルを作成する必要があります

[self.tableView dequeueReusableCellWithIdentifier:@"GroupCell"]

何も返しません。簡単な例を次に示します。

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
 // get your cell from the stack    
GroupCell_iPhone *cell=(GroupCell_iPhone*)[self.tableView dequeueReusableCellWithIdentifier:@"GroupCell"];

 // or create new one if nil. Note: you must give it the same identifier than the
 // one you are using for the dequeue. Or tableview will not be able to return you anything from the dequeing.
if(!cell)
 cell = [GroupCell_iPhone newWithIdentifier: @"GroupCell"] + autorelease];

** アップデート**

// here you are sure to have a valid cell, so you can display content according to the indexPath
// display: use a controller who will update your cell change
// note, the first method clean what was inside your cell. You can keep the subview and reuse them the same way as tableview do.
    [myDisplayClassCellController emptyCellSubview: cell];

// here you add all the display logic you want into your cell view. Note, you need indexPath
// because you need to display depending of the stack.
    [myDisplayClassCellController decorateCellWithCustomViews: cell atIndexPath: indexPath];    

**更新終了**

// then you can return back the cell to the tableView
return cell;
}
于 2012-10-29T15:59:46.600 に答える