自动调整 UITableViewCell 时 UILabel 高度不明确

Ambiguous UILabel height in autoresizing UITableViewCell

我很难实现具有自动调整单元格大小的 UITableView。我正在尝试在具有自动大小的单元格内使用带有 2 个标签的 UIStackView。

整体看起来不错,但我遇到了以下运行时问题:

我觉得我的约束应该足以满足这里的用例,但我想消除这里的歧义。

如何实现?这里通常采用什么方法?

我准备了一个示例项目,它简化了我的用例,但仍然演示了这个问题。这是我的控制器:

class ViewController: UIViewController {

    struct CellData {
        let title: String
        let subtitle: String
    }

    let table = UITableView()

    let data = [
        CellData(title: "Foo", subtitle: "Bar"),
        CellData(title: "Baz", subtitle: "FooBar")
    ]

    private let cellReuseID = "CellReuseID"

    override func viewDidLoad() {
        super.viewDidLoad()

        table.register(Cell.self, forCellReuseIdentifier: cellReuseID)
        table.dataSource = self
        table.rowHeight = UITableView.automaticDimension
        table.tableFooterView = UIView(frame: .zero)

        table.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(table)
        NSLayoutConstraint.activate([
            table.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            table.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            table.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            table.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),

        ])

    }
}

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseID) as? Cell else {
            fatalError()
        }
        cell.title = data[indexPath.row].title
        cell.subtitle = data[indexPath.row].subtitle
        return cell
    }
}

它使用的单元格:

class Cell: UITableViewCell {

    var title: String? {
        didSet {
            titleLabel.text = title
        }
    }

    var subtitle: String? {
        didSet {
            subtitleLabel.text = subtitle
        }
    }

    let titleLabel = UILabel()

    let subtitleLabel = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupView()
    }

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

    private func setupView() {
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.alignment = .top
        stackView.distribution = .fill
        stackView.spacing = 8

        stackView.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(stackView)
        NSLayoutConstraint.activate([
            stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
            stackView.topAnchor.constraint(equalTo: contentView.topAnchor)
        ])


        stackView.addArrangedSubview(titleLabel)
        stackView.addArrangedSubview(subtitleLabel)
    }
}

高度不明确的原因是因为两个标签具有相同的内容拥抱优先级。

自动布局做出“最佳猜测”并且您获得了所需的输出——但您仍然会在调试视图层次结构中看到问题。

要摆脱它,您可以给一个标签更高的拥抱优先级。

例如(在setupView()):

    titleLabel.setContentHuggingPriority(.defaultHigh + 1, for: .vertical)
    subtitleLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)