强制UITableView转储所有可重用的单元格

时间:2010-07-07 18:42:21

标签: iphone cocoa-touch uitableview

我有一个UITableView,我通过

设置了背景颜色
UIView *myView = [[UIView alloc] init];
if ((indexPath.row % 2) == 0)
    myView.backgroundColor = [UIColor greenColor];
else
    myView.backgroundColor = [UIColor whiteColor];

cell.backgroundView = myView;
[myView release];

我发现的问题是,当我编辑一个表(通过setEditing:YES ...)时,一些相同颜色不变的单元格彼此相邻。如何强制UITableView完全重绘。 reloadData做得不好。

是否有深层重绘?

5 个答案:

答案 0 :(得分:4)

之前我遇到过这个问题所以我会与你分享我是如何解决的:

您可以使用布尔标志(比如称为needsRefresh)来控制-cellForRowAtIndexPath中单元格创建的行为:

一个例子:

- (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath {
    UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:SOME_ID];
    if(!cell || needsRefresh) {
       cell = [[[UITableViewCell alloc] init....] autorelease];
    }
    //.....
    return cell;
}

因此,当您需要硬重新加载时,请将needsRefresh标记设置为YES。简单就像一个疙瘩。

答案 1 :(得分:3)

对我来说,接受的答案并没有真正起作用,因为我不知道何时将needsRefresh设置回YES。

对我有用的是:

 - (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath {
    UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:customCellIdentifier];
    if(nil == cell) {
        cell = [[UITableViewCell alloc]  initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:customCellIdentifier];
    }
    //.....
    return cell;
}

然后在需要时更改customCellIdentifier值。这样,如果切换回原始单元标识符,单元格仍然可以重复使用。

答案 2 :(得分:1)

接受的方法看起来很脏,它只是将一堆新单元与坏单元一起存储。根据您的具体情况,以下是一些解决方案:

1。 首先,对于问题中描述的情况,您不应该转储单元格并在每个循环中创建新视图。您需要标记视图,然后在获得重用单元格时从单元格中取回它:

- (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath {
    UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:SOME_ID];
    if(!cell) {
       cell = [[UITableViewCell alloc] init];

         UIView *myView = [[UIView alloc] init];    
        cell.backgroundView = myView;

        [myView setTag:5]; //<------
    }

    UIView *myView =  [cell viewWithTag:5];  //<------
    if ((indexPath.row % 2) == 0)
        myView.backgroundColor = [UIColor greenColor];
    else
        myView.backgroundColor = [UIColor whiteColor];
    return cell;
}

//then just reload the tableview.

2。 ...甚至更好,为什么不使用单元格backgrouncolor并在不创建视图的情况下更新它。

3。 一种确定清除旧缓存单元格的可靠方法,只需重新创建UITableView对象。

4。 在大多数情况下,您不需要销毁这些单元格,只需跟踪您的元素并在获取可重用单元格后更新它们。您可以标记所有元素,保留对它们的数组引用,找到它们认为视图层次结构... Im确定还有很多其他方式。

5。 下面是一个直接吹扫所有细胞的衬管,虽然不是最好的做法,因为它们可能会在未来的版本中发生变化而弄乱这些物体的内部:

[(NSMutableDictionary*)[tableview valueForKey:@"_reusableTableCells" ] removeAllObjects];

答案 3 :(得分:0)

我能够通过向表数据源添加刷新变量来解决这个问题。我为每个单元格使用了一个字典,但是有一个名为@“refresh”的额外键:@“1”,表示单元格需要刷新。一旦更新,我将该键的值设置为@“0”。因此,无论何时重新加载表,请确保该键再次返回@“0”。

答案 4 :(得分:0)

#define TABLE_VIEW_CELL_DEFAULT_ID @"cellIdentifier"
@property (nonatomic, strong) NSString *tableViewCellIdentifier;
@property (nonatomic) NSUInteger tableViewCellIdentifierCount;

// By using a different cell identifier, this effectively flushes the cell 
// cache because the old cells will no longer be used.
- (void) flushTableViewCellCache
{
    self.tableViewCellIdentifierCount++;
    self.tableViewCellIdentifier = [NSString stringWithFormat:@"%@%i", TABLE_VIEW_CELL_DEFAULT_ID, self.tableViewCellIdentifierCount];
}

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

    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.tableViewCellIdentifier];
    if (cell == nil) {
        cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:self.tableViewCellIdentifier];
    }

    // rest of method...
}