UITableViewCell - 如何在重用之前重置内容

Posted

技术标签:

【中文标题】UITableViewCell - 如何在重用之前重置内容【英文标题】:UITableViewCell - how to reset content before reusing 【发布时间】:2015-07-13 05:55:26 【问题描述】:

有一个我无法修复的烦人错误。

我有一个CustomCell,在其中我有一个子视图,可以根据对象的值改变它的颜色。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *cellIdentifier = @"CustomCell";

    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    if (cell == nil)         
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    

    MyObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];

    if ([object.redColor isEqualToNumber:[NSNumber numberWithBool:YES]]) 
        cell.colorView.backgroundColor = [UIColor redColor];
    
    else 
        cell.colorView.backgroundColor = [UIColor clearColor];
           

    return cell;

这一切正常,除非我从 tableview 中删除带有redColor = YES 的行,然后滚动显示不可见的行。可见的第一行(重用可重用单元格的第一行)具有红色,即使该行是redColor = NO。如果我再次滚动并隐藏单元格然后再次显示它,颜色将设置为 clearColor,它应该是这样的。

我认为这是因为它重用了刚刚删除的单元格。 所以我试图在重用之前重置单元格的内容。 在CustomCell.m

- (void)prepareForReuse 
    [super prepareForReuse];

    self.clearsContextBeforeDrawing = YES;
    self.contentView.clearsContextBeforeDrawing = YES;
    self.colorView.backgroundColor = [UIColor clearColor];

但这不起作用。 苹果文档说

tableView:cellForRowAtIndexPath: 中表格视图的委托在重用单元格时应始终重置所有内容。

重置内容的正确方法是什么?我必须从超级视图中删除子视图吗?

提前致谢

【问题讨论】:

你好@SFF检查我的答案。,,, 【参考方案1】:

这似乎行得通。

我在CustomCell.mCustomCell.mprepareForReuse 时删除了单元格的 contentView

- (void)prepareForReuse 
    [super prepareForReuse];

    // Clear contentView
    BOOL hasContentView = [self.subviews containsObject:self.contentView];    
    if (hasContentView) 
        [self.contentView removeFromSuperview];
    

再次添加到cellForRowAtIndexPath

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

    // Cell
    static NSString *cellIdentifier = @"CustomCell";

    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    if (cell == nil)         
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    

    // Restore contentView
    BOOL hasContentView = [cell.subviews containsObject:cell.contentView];
    if (!hasContentView) 
        [cell addSubview:cell.contentView];
    

    // Configure cell
    MyObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];

    if ([object.redColor isEqualToNumber:[NSNumber numberWithBool:YES]]) 
        cell.colorView.backgroundColor = [UIColor redColor];
    
    else 
        cell.colorView.backgroundColor = [UIColor clearColor];
           

    return cell;

希望这会对某人有所帮助。

【讨论】:

这不是太耗费资源了吗?而且它不再“可重复使用”了? 我想知道这会有多贵。如果你计算量很大,你的 FPS 可能会显着下降,甚至低于 60。【参考方案2】:

您可以使用此 tableview 委托方法来更改可见性(例如背景颜色)但不能更改数据:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

【讨论】:

我尝试在willDisplayCell 中设置颜色,但结果相同。它不会清除重用单元格的旧内容... 你可以尝试添加 [cell.contentView setNeedsDisplay];在返回单元格之前; 嗯,我试过打电话给[cell.contentView setNeedsDisplay];,但还是不行……我也试过[cell.contentView layoutIfNeeded];,但没有运气:(【参考方案3】:
        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        
            NSString *cellIdentifier = [NSString stringWithFormat:@"CustomCell %ld",(long)indexPath.row];


            CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
            cell = nil;

            if (cell == nil)
            
                cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];


                MyObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];

                if ([object.redColor isEqualToNumber:[NSNumber numberWithBool:YES]]) 
                
                    cell.colorView.backgroundColor = [UIColor redColor];
                
                else
                
                    cell.colorView.backgroundColor = [UIColor clearColor];
                


            return cell;
        

【讨论】:

你确定这是正确的代码吗??为什么要根据indexpath更改cellIdentifier??在 cell == nil 之前设置 cell = nil 也不起作用.....谢谢您的帮助... 我试过了,但由于 cellIdentifier 错误,导致应用程序崩溃。而且,如果我设置单元格 = nil,它会使所有单元格变为空白。 你好@TuğrulÖzdemir 请告诉我重用机制的正确方法。 实际上,并没有完全杀死 :) 为每一行使用不同的 cellIdentifier 会为每一行创建新的单元格。如果我有太多行会发生什么。我更喜欢对相似的行使用相同的标识符 单元格 = nil; if (cell == nil) 没有意义【参考方案4】:

如果您想从重用单元列表中删除所有单元,请使用:

[tblView setValue:nil forKey:@"_reusableTableCells"]

如果您想从重复使用的单元格列表中删除单个单元格,请使用:

NSString* cellID = [NSString stringWithFormat:@"cellID%ld%ld",(long)indexPath.section,(long)indexPath.row];
        NSMutableDictionary *temp1 = (NSMutableDictionary*)[tblView valueForKey:@"_reusableTableCells"];
        [temp1 removeObjectForKey:cellID];
        [tblView setValue:temp1 forKey:@"_reusableTableCells"];

其中 cellID 是在初始化单元时设置的唯一重用单元标识符。

【讨论】:

以上是关于UITableViewCell - 如何在重用之前重置内容的主要内容,如果未能解决你的问题,请参考以下文章

我的 UITableViewCell 正在重用以前的单元格 UIImage

iOS - 如何在不同的 UITableViewCell 中重用 UIView

关于单元重用的自定义 UITableViewCell 约束问题

如何创建不可重用的 UITableViewCell

UITableViewCell的重用机制

如何防止 UITableViewCell 重复和重用?