Ios 使用Autolayout的可扩展UITableView单元格会导致UIViewAlertForUnsatifiableConstraints

Ios 使用Autolayout的可扩展UITableView单元格会导致UIViewAlertForUnsatifiableConstraints,ios,swift,uitableview,autolayout,Ios,Swift,Uitableview,Autolayout,我正在尝试使用UITableViewAutomaticDimension行高和单元格自动布局的组合来制作可扩展单元格。为了使事情变得简单,我从以下简单的代码开始,我希望这些代码能够工作: import UIKit class ViewController: UITableViewController { let cells = [Cell(), Cell(), Cell()] override func viewDidLoad() { super.viewD

我正在尝试使用
UITableViewAutomaticDimension
行高和单元格自动布局的组合来制作可扩展单元格。为了使事情变得简单,我从以下简单的代码开始,我希望这些代码能够工作:

import UIKit

class ViewController: UITableViewController {

    let cells = [Cell(), Cell(), Cell()]

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 50

        for cell in cells {
            cell.tableView = tableView
        }
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return cells[indexPath.row]
    }
}

class Cell: UITableViewCell {

    var cons: NSLayoutConstraint?
    var tableView: UITableView?

    init() {
        super.init(style: .default, reuseIdentifier: nil)

        let button = UIButton()
        contentView.addSubview(button)
        button.addTarget(self, action: #selector(Cell.tapped(_:)), for: .touchUpInside)
        button.setTitle("Press me", for: .normal)
        button.setTitleColor(.red, for: .normal)

        button.translatesAutoresizingMaskIntoConstraints = false

        // constraining the button to the view, so that buttons height would define cell height
        let constraints = [
            button.topAnchor.constraint(equalTo: contentView.topAnchor),
            button.rightAnchor.constraint(equalTo: contentView.rightAnchor),
            button.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
            button.leftAnchor.constraint(equalTo: contentView.leftAnchor),
        ]

        NSLayoutConstraint.activate(constraints)
        cons = button.heightAnchor.constraint(equalToConstant: 100)
        cons?.isActive = true
    }

    func tapped(_ sender: UIButton) {
        // change the height of the button, thus of the contentView too (since the button is constrained to the contentView)
        if cons?.constant == 100 {
            cons?.constant = 200
        } else {
            cons?.constant = 100
        }
        // tell the tableView to redraw itself to apply the change
        tableView?.beginUpdates()
        tableView?.setNeedsDisplay()
        tableView?.endUpdates()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
现在,这似乎可以工作了,但是,我仍然会收到
UIViewAlertforUnsatifiableConstraints
警告,并显示以下消息:

(
"<NSLayoutConstraint:0x17408c7b0 V:|-(0)-[UIButton:0x109e10290'Press me']   (active, names: '|':UITableViewCellContentView:0x109e0fd90 )>",
"<NSLayoutConstraint:0x17408c8a0 UIButton:0x109e10290'Press me'.bottom == UITableViewCellContentView:0x109e0fd90.bottom   (active)>",
"<NSLayoutConstraint:0x17408c990 UIButton:0x109e10290'Press me'.height == 200   (active)>",
"<NSLayoutConstraint:0x17408db10 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x109e0fd90.height == 100   (active)>"
)

 Will attempt to recover by breaking constraint 
 <NSLayoutConstraint:0x17408c990 UIButton:0x109e10290'Press me'.height == 200   (active)>
如何删除警告


我知道,简单地将高度限制的优先级更改为999将删除警告,但在我看来,删除它是一种黑客行为,而不是一种解决方案。如果我错了,请解释。谢谢。

删除高度约束,即200,因为它与顶部和底部约束冲突


希望这会有所帮助。

将高度限制优先级设置为999可能感觉像是一种黑客行为,但根据苹果的文档:

注意不要觉得有义务使用所有1000个优先级值。事实上,优先级应该围绕系统定义的低(250)、中(500)、高(750)和所需(1000)优先级进行聚集。您可能需要使约束比这些值高或低一个或两个点,以帮助防止打结。如果您要做的远远不止这些,您可能需要重新检查布局的逻辑

可能不那么直观:

“我希望按钮高度控制单元格高度,因此降低其优先级???”

但是,这似乎确实是一种“正确”的方式


Ref:

将优先级更改为高度约束的下限高度约束定义单元的展开/折叠高度。它必须在那里。
tableView?.beginUpdates()
tableView?.setNeedsDisplay()
tableView?.endUpdates()