UITableViewCell中的约束未被计算

时间:2018-03-28 06:58:25

标签: ios autolayout constraints

我有以下单元格,其中包含以编程方式设置的约束:

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方法只是添加约束的辅助方法。约束设置正确(Autolayout没有问题)。

然后在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中创建了以下布局(这显然是错误的): enter image description here

如果我将约束的设置移动到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
 }
}

enter image description here

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

感谢您的回答:)

修改我发现,当我在updateConstraints中呼叫cell.updateConstraintsIfNeeded()cell.setNeedsUpdateConstraints()时,它适用于cellForRowAtIndexPath。为什么我们需要告诉单元格再次计算约束?在使用IB ...

添加约束时,我们不需要这样做

1 个答案:

答案 0 :(得分: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(){ ... }内嵌入了约束设置。因此,在调用此函数时,您的约束已准备好应用。无需系统调用。