在 `cellForRowAt` 中激活 NSLayoutConstraint 直到滚动后才会呈现

Posted

技术标签:

【中文标题】在 `cellForRowAt` 中激活 NSLayoutConstraint 直到滚动后才会呈现【英文标题】:Activating NSLayoutConstraint in `cellForRowAt` is not rendering until after scrolling 【发布时间】:2017-04-05 07:56:45 【问题描述】:

我需要支持 UITableViewAutomaticDimension(用于动态高度),但约束有所不同:有些需要激活,有些不需要。

我在安装了aConstraint bConstraint 的情况下设置了情节提要。我在tableView(_:cellForRowAt:) 中根据需要激活/停用它们。

class ViewController: UIViewController 
    @IBOutlet weak var tableView: UITableView! 
        didSet 
            tableView.estimatedRowHeight = 10
            tableView.rowHeight = UITableViewAutomaticDimension
        
    


class MyTableViewCell: UITableViewCell 
    @IBOutlet var aConstraint: NSLayoutConstraint!
    @IBOutlet var bConstraint: NSLayoutConstraint!


extension ViewController: UITableViewDataSource 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 20
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! MyTableViewCell
        cell.contentView.translatesAutoresizingMaskIntoConstraints = false
        if indexPath.row % 2 == 0 
            NSLayoutConstraint.deactivate([cell.aConstraint])
            NSLayoutConstraint.activate([cell.bConstraint])
         else 
            NSLayoutConstraint.deactivate([cell.bConstraint])
            NSLayoutConstraint.activate([cell.aConstraint])
        
        return cell
    

问题

初始可见布局忽略所有这些激活/停用,所有单元格都与原始情节提要状态相同。

您会注意到只有在滚动后才会应用正确的约束。

尝试

我确实尝试了一些cell.setNeedsUpdateConstraints(); cell.updateConstraintsIfNeeded(); cell.layoutIfNeeded(); ...但没有成功

在https://github.com/Coeur/dynamic-cell-height分享的示例项目

【问题讨论】:

【参考方案1】:

在安装了“aConstraint”和“bConstraint”的情况下设置故事板,但将“aConstraint”的优先级较低以删除警告并且它可以工作:)

【讨论】:

它适用于设置为优先级 999 的 aConstraintbConstraint。谢谢。【参考方案2】:

在代码中设置约束的几个问题。

1.

UILabel intrinsicContentSize 将参与自动布局。 自动布局系统会根据intrinsicContentSize创建宽度和高度约束。

您在xib文件中明确设置了标签的高度约束,导致歧义,然后添加了垂直中心Y约束来解决问题。

2

如果您想尝试激活或停用约束,您可能需要使用简单的 UIView。

3

如果你想做各种高度的行,利用intrinsicContentSize,设置UILabel的preferredWidth。

【讨论】:

UILabel 在 github 上被移除。问题的重点是在cellForRowAt 中激活未安装的约束在滚动完成之前无效。

以上是关于在 `cellForRowAt` 中激活 NSLayoutConstraint 直到滚动后才会呈现的主要内容,如果未能解决你的问题,请参考以下文章

如何避免 tableView(_:cellForRowAt) 中的崩溃?

如何在uitableview的cellForRowAt函数中按标题日期对响应进行排序

在 cellForRowAt 中不工作 UITableView 但 numberOfRowsInsection 在 Swift 中工作

numberOfRowsInSection 已调用但 cellForRowAt 未调用

简化 TableView 中的 cellForRowAt

未使用 reloadData() 方法调用 cellForRowAt indexPath