使用Autolayout的可扩展UITableView单元导致UIViewAlertForUnsatisfiableConstraints [英] Expandable UITableView Cell using Autolayout results in UIViewAlertForUnsatisfiableConstraints

查看:120
本文介绍了使用Autolayout的可扩展UITableView单元导致UIViewAlertForUnsatisfiableConstraints的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 UITableViewAutomaticDimension 行高和Autolayout单元格的组合来制作可扩展单元格。为了简单起见,我开始使用以下简单的代码,我希望它可以工作:

I am trying to make expandable cells using combination of UITableViewAutomaticDimension row height and Autolayout of the cells. To make things simple, I started with the following simple code, that I expected to work:

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")
    }
}

现在这似乎有效,但是,我仍然会收到 UIViewAlertForUnsatisfiableConstraints 警告,并显示以下消息:

Now this seems to be working, however, I still do get UIViewAlertForUnsatisfiableConstraints warning with the following message:

(
"<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)>

似乎(或当前)行高估计与我提供的自动布局约束相冲突。尽管如此,使用以下代码刷新tableView将按预期显示:

It seems that the estimated (or current) row height collides with the autolayout constraint provided by me. Still, refreshing the tableView using following code will display it as expected:

tableView?.beginUpdates()
tableView?.setNeedsDisplay()
tableView?.endUpdates()

如何删除警告?

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

I am aware that simple changing the priority of the height constraint to 999 will remove the warning, but it seems to me as a hack to remove it, not as a solution. If I am mistaken, please explain. Thanks.

推荐答案

将高度约束优先级设置为999可能感觉就像黑客一样,但根据Apple的文档:

Setting the height constraint priority to 999 may feel like a hack, but according to Apple's docs:


注意不要觉得有义务使用所有1000个优先级值。事实上,优先级应围绕系统定义的低(250),中(500),高(750)和所需(1000)优先级进行一般集群。您可能需要制作比这些值高一点或两点的约束,以帮助防止关联。如果你要超越它,你可能想要重新检查你的布局的逻辑。

NOTE Don’t feel obligated to use all 1000 priority values. In fact, priorities should general cluster around the system-defined low (250), medium (500), high (750), and required (1000) priorities. You may need to make constraints that are one or two points higher or lower than these values, to help prevent ties. If you’re going much beyond that, you probably want to reexamine your layout’s logic.

可能比直觉要差一点:

我希望按钮高度控制单元格高度,所以 降低 优先级????

"I want the button height to control the cell height, so lower its priority????"

但是,这似乎是正确的做法。

But, that does appear to be the "correct" way to do it.

Ref: https: //developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/AnatomyofaConstraint.html#//apple_ref/doc/uid/TP40010853-CH9-SW19

这篇关于使用Autolayout的可扩展UITableView单元导致UIViewAlertForUnsatisfiableConstraints的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆