带有 UILabel 子视图缓存问题的 UITableViewCell

Posted

技术标签:

【中文标题】带有 UILabel 子视图缓存问题的 UITableViewCell【英文标题】:UITableViewCell with UILabel subview caching issue 【发布时间】:2012-07-19 20:58:39 【问题描述】:

首先,请不要告诉我这是重复的。我知道这个问题已被多次询问和回答,但即使在阅读了其他人的解决方案后,我似乎仍然无法让我的代码正常工作。

我的 UITableViewCell 包含 UILabel 子视图时遇到问题。 UILabel 有时不会出现在某些单元格中,直到我滚动离开这些单元格并返回它们。这是我用来自定义单元格的代码:

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

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

UILabel *label;

if (cell == nil) 

    // cell is nil, create it

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:CellIdentifier];


    label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
    label.tag = 888;

 else 

    label = (UILabel*)[cell.contentView viewWithTag:888];
    [label removeFromSuperview];



label.text = @"Label Text";
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
label.center = CGPointMake(cell.contentView.frame.size.width-label.frame.size.width/2-20, cell.contentView.frame.size.height/2);
[cell.contentView addSubview:label];

// customize cell text label
cell.textLabel.text = @"Cell Text";
cell.textLabel.textColor = [UIColor darkGrayColor];

return cell;

当 dequeueReusableCellWithIdentifier:CellIdentifier 返回非 nil 值时,标签似乎正确显示,但如果返回值为 nil 且必须实例化新单元格,则不会显示。

如果有人知道为什么会发生这种情况,我们将不胜感激。

【问题讨论】:

您好,我不明白您为什么要创建新标签并插入它们。基本方法是在编辑器或代码中准备一个单元格并重用它。而重用意味着清洁和格式化,甚至不重新排列找到的单元格。所以对我来说,你似乎在浪费资源。我建议您在编辑器中准备一个自定义单元格,将其分配给一个类并重用它。或者您重新排列标签是否有特定原因? 我不确定我明白你在说什么。我正在尝试在表格单元格的最右侧添加一个标签(与单元格的 textLabel 属性分开),并且每次表格视图出现时标签文本都可能发生变化。 【参考方案1】:

我看到了一些你想做的事情。

1) 阅读“sizeToFit” - 描述说如果视图没有超级视图,您可能会得到奇怪的结果。

2) 创建视图时,立即将其添加到单元格中。

3) 调整单元格大小后,获取其大小,然后计算正确的框架 - 我建议不要使用“中心”,但我不知道您的代码不适用于事实。

4) 在改变中心以改变框架之前,硬编码如下:

CGRect r = label.frame;
r.origin = (CGPoint) 20, 20 ;
label.frame = r;

这至少会让您相信新单元和旧单元都在正常工作。然后你可以计算出你真正想要的帧,或者进一步使用中心。

【讨论】:

【参考方案2】:

不确定问题的原因,但您可以进行一些改进。也许其中一个解决了这个问题:

    在 dequeu 场景中,您从视图中删除标签,只是将其添加回来。相反,您应该将其保留在视图层次结构中。

    为了避免一直调整和移动标签。为什么不让它足够宽,将文本设置为右对齐。这样,您不必在 dequeue 场景中调整移动标签的大小。

【讨论】:

【参考方案3】:

看来问题可能出在修改 cell.textLabel 上。该站点上的其他帖子建议,每当修改此标签时,实际上都会创建一个新标签并将其添加到单元格的内容视图中(而不是仅修改现有标签)。设置cell.textLabel.backgroundColor = [UIColor clearColor]; 似乎解决了问题

我仍然对此有点困惑,因为即使最后添加我的自定义标签子视图(在为 cell.textLabel 设置属性之后)也不能解决问题 - cell.textLabel 的背景颜色必须设置为透明/清除。

【讨论】:

【参考方案4】:

有三点不合适:

if (cell == nil)  // cell is nil, create it

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:CellIdentifier];

    label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
    label.tag = 888;
    [cell.contentView addSubview:label]; // (1) DO THIS HERE

 else 

    label = (UILabel*)[cell.contentView viewWithTag:888];
    // (2) DON'T DO THIS:  [label removeFromSuperview];



label.text = @"Label Text";
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
label.center = CGPointMake(cell.contentView.frame.size.width-label.frame.size.width/2-20, cell.contentView.frame.size.height/2);
// (3) DON'T DO THIS HERE: [cell.contentView addSubview:label];
....

我假设 ARC 已打开,否则在将其添加到 contentView 后您需要一个 [label release]。

【讨论】:

以上是关于带有 UILabel 子视图缓存问题的 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章

UILabel 阻止 UIButton 显示,直到您从调试视图层次结构继续

带有子视图的可变 UITableCellView 高度

滚动后 UICollectionViewCells 子视图呈现错误

以编程方式使用自动布局实现带有子视图的 uiview 子类

iOS 使用带有 UILabel 的 UITapGestureRecognizer 滑动到下一页

为啥带有 UILabel 的嵌套 UIStackViews 需要 Y 位置和高度约束?