未计算 UITableViewCell 中的约束

Posted

技术标签:

【中文标题】未计算 UITableViewCell 中的约束【英文标题】:Constraints in UITableViewCell not being calculated 【发布时间】:2018-03-28 06:58:24 【问题描述】:

我有以下单元格以编程方式设置约束:

class RadioButtonCell: UITableViewCell 

static let identifier = "RadioButtonCell"

let radioButton = RadioButton()
let labelTitle = UILabel()

private var didUpdateConstraints = false

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setupSubViews()


required init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


private func setupSubViews() 
    radioButton.translatesAutoresizingMaskIntoConstraints = false
    labelTitle.translatesAutoresizingMaskIntoConstraints = false
    contentView.addSubview(radioButton)
    contentView.addSubview(labelTitle)


override func updateConstraints() 
    super.updateConstraints()
    if !didUpdateConstraints 
        radioButton.anchor(leading: contentView.leadingAnchor, padding: UIEdgeInsets(top: 0, left: Constants.UI.defaultMarginX2, bottom: 0, right: 0))
        radioButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        labelTitle.anchor(leading: radioButton.trailingAnchor, padding: UIEdgeInsets(top: 0, left: Constants.UI.defaultMarginX2, bottom: 0, right: 0))
        labelTitle.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        didUpdateConstraints = true
    
  

anchor 方法只是添加约束的辅助方法。约束设置正确(自动布局没有问题)。

然后在cellForRowAtIndexPath 方法中创建单元格,如下所示:

guard let cell = tableView.dequeueReusableCell(withIdentifier: RadioButtonCell.identifier, for: indexPath) as? RadioButtonCell else  return UITableViewCell() 
radtioButtonController.addButton(cell.radioButton)
cell.labelTitle.text = "test"
return cell

这在 tableView 中创建了以下布局(这显然是错误的):

如果我将约束的设置移动到setupSubViews() 方法,则布局是正确的:

class RadioButtonCell: UITableViewCell 

static let identifier = "RadioButtonCell"

let radioButton = RadioButton()
let labelTitle = UILabel()

private var didUpdateConstraints = false

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setupSubViews()


required init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


private func setupSubViews() 
    radioButton.translatesAutoresizingMaskIntoConstraints = false
    labelTitle.translatesAutoresizingMaskIntoConstraints = false
    contentView.addSubview(radioButton)
    contentView.addSubview(labelTitle)
    radioButton.anchor(leading: contentView.leadingAnchor, padding: UIEdgeInsets(top: 0, left: Constants.UI.defaultMarginX2, bottom: 0, right: 0))
    radioButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
    labelTitle.anchor(leading: radioButton.trailingAnchor, padding: UIEdgeInsets(top: 0, left: Constants.UI.defaultMarginX2, bottom: 0, right: 0))
    labelTitle.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
 

为什么会这样?我认为我们应该在updateConstraints 方法中设置约束...

谢谢你的回答:)

编辑我发现,当我在cellForRowAtIndexPath 中调用cell.updateConstraintsIfNeeded()cell.setNeedsUpdateConstraints() 时,它适用于updateConstraints。为什么我们需要告诉单元格再次计算约束?使用 IB 添加约束时,我们不需要这样做...

【问题讨论】:

【参考方案1】:

嗯,在您的第一个示例中,您不只是将约束添加到 init 中的 UI 元素。您只需设置子视图。

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setupSubViews()
    // No explicit constraint setup happened

要设置约束,您已经覆盖了override func updateConstraints() ... 方法。我们来看看official documentation from Apple。

简而言之,当您通知系统您需要更新约束时,您的覆盖将生效。因此,您需要通过调用 setNeedsUpdateConstraints()updateConstraintsIfNeeded() 来明确通知系统。



让我们看看你的第二个例子。您在 private func setupSubViews() ... 中嵌入了约束设置。因此,在调用此函数时,您的约束已准备好应用。无需系统调用。

【讨论】:

好的,谢谢!后续问题:在 updateConstraints() 中设置约束时,我遇到了不需要显式调用 setNeedsUpdateConstraints() 或 updateConstraintsIfNeeded() 的视图。在什么情况下会发生这种情况? 好的,如果您遇到这种情况,那么不知何故,setNeedsUpdateConstraints()updateConstraintsIfNeeded() 中的任何一个都会被调用。通常这是通过setup... 方法完成的,例如self.setNeedsUpdateConstraints()

以上是关于未计算 UITableViewCell 中的约束的主要内容,如果未能解决你的问题,请参考以下文章

UITextView 高度未在 UITableViewCell 中调整大小

如何动态设置 UIView 约束?

带有约束更新的 UITableViewCell 导致 UITableView 跳来跳去

UITableViewCell 中的约束不起作用

缩进 UITableViewCell 中的所有自动布局约束

UITableViewCell中的自动布局约束不匹配