UITableViewCell 约束更新仅在滚动后发生

Posted

技术标签:

【中文标题】UITableViewCell 约束更新仅在滚动后发生【英文标题】:UITableViewCell constraint updates only happening after scrolling 【发布时间】:2019-03-27 23:16:52 【问题描述】:

我遇到了一个烦人的情况。我发现了类似的问题,但答案对我没有帮助,所以我希望能得到一些建议。

我有一个自定义 UITableViewCell,我在其中使用 .xib 文件。当应用程序加载时,我会获取一些数据,一旦检索到,我会重新加载我的 tableView。单元格显示一张图片和一些标签,我需要标签根据单个单元格中内容的文本宽度调整它们的大小。假设我有这个给cellForRowAt indexPath

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    guard
        let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.reuseIdentifier, for: indexPath) as? MyCell,
        indexPath.row < myDataArray.count
    else  return UITableViewCell() 

    let dataForCell = myDataArray[indexPath.row]
    cell.configure(with: dataForCell)
    cell.layoutIfNeeded()
    return cell

现在在我的MyCell.swift 文件中,在configure(with:) 方法中设置标签文本,然后我还调用了一个名为setWidths() 的私有方法,它使用我添加到UILabel 的扩展名返回给我的宽度文本设置后的标签 - 我做了一些基本的计算来调整我想要的标签约束。

我遇到的唯一问题是,当表格视图最初加载时,标签的宽度没有正确更新,但是当我向下滚动到最初超出框架的单元格时,它们会正确显示,然后当我向上滚动到最初在框架中且未对齐的单元格时,它们也会正确显示。

我知道我以前遇到过这样的问题,但通常在单元格上调用 layoutIfNeeded() 可以解决问题。不是这个时候。

我知道这与可重用单元格和出队的想法有关,但为什么第一组单元格的布局不遵循相同的规则?这些是用户看到的第一个单元格,我需要它们是正确的!

有人对我有什么建议吗?

编辑

我想我已经解决了这个问题,但是我仍然不知道该怎么做。我必须根据单元格框架的可用情况调整计算出的标签宽度。我添加了一些打印语句来查看单元格宽度是否发生了变化,并且确实如此。在setWidths() 方法中,我添加了print(self.frame.width),当tableView 第一次加载时,它会为每个单元格打印出325.0,但是当我滚动并布局新单元格时,它会更改为414.0(使用iPhone 8 Plus模拟器)。是什么导致单元格的框架宽度从初始布局到重新使用单元格时发生变化?

【问题讨论】:

为什么不直接设置约束并使用 UITableviewAutomaticDimension 而不是自己计算大小? @LuisPerez - 我对每个单元格的高度使用自动尺寸,但我不能将它用于这些单独标签的宽度。我有一个非常具体的模型,我必须遵循标签需要根据相邻标签的可用空间缩小的地方。在这里解释起来有点太复杂了,不会让每个人都感到困惑。我对我的问题添加了一个编辑,让我发现发生了什么。 我想我现在明白了,在您计算单元格宽度的那一刻,contentView 尚未呈现,您需要做的是更改您的配置方法以获取宽度,在那里你可以发送 tableview 框架的宽度,它将是这样的:cell.configure(with: DataForCell, width: tableview.frame.width) 编辑:之后,使用该宽度来计算标签大小 @LuisPerez - 是的,你是对的。我刚刚尝试在viewDidLoad 中添加打印语句,然后在cellForRowAt 中再次添加 - 出于某种原因在viewDidLoad 我的self.view.frame.width = 375.0 中,但随后在cellForRowAtself.view.frame.width = 414.0 使我的数学正确。如果您想添加答案,我会接受。那么 ios 是否只是针对通用帧大小进行布局?为什么从375.0 更改为414.0?这就是我不明白的地方 【参考方案1】:

这里的问题是,当单元格尚未呈现时,您正在计算您的尺寸,更新您的配置方法以获取 tableview 宽度,例如 cell.configure(with: DataForCell, width: tableview.frame.width),然后使用该宽度来配置您的尺寸,以及为什么它从 375 变为 414,答案是你得到了普通 iphone 的宽度,当视图被渲染时,它变为加号。

【讨论】:

@LuizPerez - 我在计算中犯了一个愚蠢的错误,我刚刚意识到,以防其他人有类似的问题。在计算一个约束的宽度变化之前,我已经根据其文本大小更改了另一个标签的宽度,并且在我的计算中我使用了otherLabel.frame.width 而不是我的 IBOutlet otherLabelWidthConstraint.constant。所以我的计算是使用另一个标签的框架(它还没有改变,并且设置为它在 XIB 文件中的排列方式),而不是使用我改变它的宽度,但它还没有更新.

以上是关于UITableViewCell 约束更新仅在滚动后发生的主要内容,如果未能解决你的问题,请参考以下文章

在缩放时,使用UIWebView scrollView更新UITableViewCell中的约束无法正常工作

UITableViewCell 标签不需要的缩进

UITableViewCell 只在滚动后显示附件

滚动时更新 UITableViewCell

UITableViewCell 在位置回调后不更新,直到滚动或选择

iOS 在 UITableViewCell 中以编程方式设置 UIImageView 约束在滚动 tableview 时变得混乱