23

我有一个自定义UITableViewCell子类,它在 Interface Builder 中应用了自动布局约束。该单元格包含多个视图,包括一个UITextField.

相关地,它的大小UITextField受到限制,使其与下一个视图之间存在默认的水平间距。

单元格实例化如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"ProgressCell";
    ProgressCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
                                                     forIndexPath:indexPath]

    cell.textField.text = @"Some string that is different for each cell";

    return cell;
}

当单元格第一次出现时,UITextField超出了正确的框架,并出现在UIView其右侧的后面。但是,当我将单元格滚动出屏幕、暂停然后向后滚动时,文本会被正确截断。

下面显示了一个示例(在第二次编辑时)。

我曾尝试调用[cell setNeedsLayout][cell setNeedsDisplay]中的单元格cellForRowAtIndexPath,并在延迟后执行它们。两者都无效。

什么是滚动屏幕导致单元格正确显示,我该如何复制或修复潜在问题?

编辑:

打电话

[self.tableView reloadData];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

为了重新加载单元格,似乎会导致布局第一次正确显示。

但是,它现在(偶尔)在滚动时中断(即,当向上滚动时,布局约束现在没有正确应用)。

打电话似乎不能解决这个问题[cell setNeedsLayout]cellForRowAtIndexPath

编辑2:

如此处所示的顶部单元格正确显示(与底部单元格一样),直到我向下滚动屏幕。从此消失了。

这反映了第一次编辑时的问题 - 这是第二次渲染的问题(让我认为它可能与重用单元格有关?)

4

3 回答 3

37

如果您在UITableViewCell子类textLabel或上命名属性defaultTextLabel,则 IB 将忽略您指定的约束并用默认约束覆盖它们,不会发出警告。

即使在 IB 中使用自定义样式设计的单元格也是如此,这些单元格没有可见textLabeldetailTextLabel属性。

UIImageView如果在子类上添加类型属性的属性UITableViewCell并将其命名,也会发生这种情况imageView

于 2013-02-21T23:53:46.443 回答
8

按照这个多行UILabelGitHub issue,这是一个挥之不去的 iOS 错误。

我发现在 iOS 9+ 中,这种情况多发生在编辑模式下,具有很大的不可预测性。

以下解决方法仅部分有效:它需要重绘UITableView两次,但仍不能涵盖所有场景。

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.setNeedsLayout()
    tableView.layoutIfNeeded()
    tableView.reloadData()
}

笔记:

  • UsingUITextView是 multi line 的一个很好的替代方案UILabel,没有错误。UITextView也没有表现出任何IULabel其他奇怪现象,例如对齐错误闪烁
  • SO-25947146上还有一个替代解决方案,它对我不起作用,但值得一提。
  • 似乎self.tableView.editingtrue
  • 使用低值来tableView.estimatedRowHeight减少发生率
  • SwiftArchitect/TableViewControllerRowHeightBug上的错误演示要点
于 2016-02-06T01:10:56.760 回答
0

就我而言,我在 viewDidAppear 中调用方法 tableView.reloadData() 并且布局正确显示

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.tableView.reloadData()
}
于 2021-10-29T08:14:45.760 回答