UITableViewCell 重用时为空白

Posted

技术标签:

【中文标题】UITableViewCell 重用时为空白【英文标题】:UITableViewCell blank when reused 【发布时间】:2015-07-06 08:39:52 【问题描述】:

我将 UITableView 与情节提要中定义的各种单元格一起使用。样式都是“字幕”。对于一种单元格类型,标识符是“标签”,它在我的表中的两个位置使用,因此被提取:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"label" forIndexPath:indexPath];

填充文本标签的代码是:

// cell 0,0 section,row
cell.textLabel.text = @"";
cell.detailTextLabel.text = @"Subtitle 1";
NSLog(@"%@",cell); // <UITableViewCell: 0x13ee183c0; frame = (0 26; 320 52); text = ''; ...

// cell 6,0
cell.textLabel.text = @"Version";
cell.detailTextLabel.text = @""; // using @" " instead cures the problem
NSLog(@"%@",cell); // <UITableViewCell: 0x13ee183c0; frame = (0 1022; 320 52); text = 'Version'; ...

启动时,单元格 0,0 会显示正确的文本。当我向下滚动时,单元格 6,0 显示正确的文本。 但是,当我滚动回顶部时,单元格 0,0 是空白的(重复使用的 cell.text = 'Version')。如果我将单元格 0,0 滚动到视图之外,然后滚动回顶部,单元格 0,0 就可以了(重复使用的 cell.text = '')。

在单元格 6,0 中,如果我使用 @" " 而不是 @"" 代替 detailTextLabel,那么问题就会消失,但单元格中的间距不正确(“版本”不再垂直居中)。

奇怪的是,cell.text(已弃用的属性)在第二种情况下不为空,但在 0.0 中将 cell.text 显式设置回 nil 或 @"" 没有任何区别。

在第 6 节中重复使用时,为什么第一个单元格是空白的?

编辑添加:

这是我的代码的简化版本,它仍然演示了问题。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return 10;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return 2;


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

    NSString *resueIdentifier;
    if ( indexPath.section == 0  &&  indexPath.row == 0 ) 
        resueIdentifier = @"label"; // in the nib, this is a cell with no other controls
     else if ( indexPath.section == 6  &&  indexPath.row == 0 ) 
        resueIdentifier = @"label";
     else  // all other rows for demo contain a UISwitch
        resueIdentifier = @"switch"; // in the nib, this is a cell with a UISwitch (e.g., Settings)
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:resueIdentifier forIndexPath:indexPath];
    // never nil -- that always returns a cell from the storyboard/nib

    if ( indexPath.section == 0  &&  indexPath.row == 0 ) 
        cell.textLabel.text = @""; // no title
        cell.detailTextLabel.text = @"This is detail text";
     else if ( indexPath.section == 6  &&  indexPath.row == 0 ) 
        cell.textLabel.text = @"Version X";
        cell.detailTextLabel.text = @""; // no detail text (this causes the problem)
     else 
        cell.textLabel.text = @"X";
        cell.detailTextLabel.text = @"Y";
    
    return cell;

要查看问题,请向下滚动到第 6 部分(请参阅单元格中的“版本 X”),然后滚动回顶部。顶行将为空(应显示“这是详细文本”)。接下来向下滚动,使第 0 行不可见,然后滚动回顶部(第 0 行将显示详细文本)。

这是我的故事板示例(选择了“标签”行):

【问题讨论】:

粘贴整个cellForRowAtIndexPath的代码 如果没有看到整个方法,很难说哪里出了问题 - 但从你放在这里的内容来看,我想问如果你期待静态,是否有必要使用动态单元格特定位置的内容?如果您有明确的内容,您可能需要考虑静态单元格。 @Shai:我添加了更多代码。 @Derek:我的 UITableView 是一个设置页面。每个单元都可以有一个开关、一个滑块、一个步进器等,并且每种类型都有一个(动态)原型。一种类型是“标签”(标识符)并且没有添加控件。每个部分和行的特定类型在查找表中指定,以及有关该行的文本和其他细节。如果我想更改 UITableView 行,我只需更改查找表即可。 【参考方案1】:

请使用这个:

 static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
    
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        NSLog(@"new one");
    

希望这能有所帮助/

【讨论】:

当使用带有原型单元的情节提要时,dequeueReusableCellWithIdentifier:forIndexPath: 从不返回 nil。【参考方案2】:

解决方法:在tableView:cellForRowAtIndexPath:末尾添加[cell layoutIfNeeded] (在使用具有各种类型原型单元的情节提要时,这可能是 Apple 的错误吗?)

https://***.com/a/27699358/236415推荐

【讨论】:

是的,这是在 ios9 中修复的 iOS8 错误。见***.com/questions/25793074/…。

以上是关于UITableViewCell 重用时为空白的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 没有正确重用?

UITableViewCell重用的问题

UItableviewCell 单元格重用问题

UITableViewCell的重用机制原理

UITableViewCell的重用机制

UITableViewCell 重用后 topLayoutGuide 搞砸了