在 iOS "Unable to simultaneously satisfy constraints" 中获取 UI 布局的警告

Getting Warning for UI Layout in iOS "Unable to simultaneously satisfy constraints"

我已经以编程方式创建了 UITableviewCell 并尝试在 table 视图中加载 Cell 只有一个 imageView 和 UIlabel.

虽然 UI 看起来不错,但我看到了这个警告:

无法同时满足约束条件。 可能至少以下列表中的约束之一是您不想要的。

 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x60000147f200 V:|-(0)-[UIView:0x7f897ea24a00]   (active, names: '|':SampleTest.MemesTableViewCell:0x7f897ea2aaf0 )>",
    "<NSLayoutConstraint:0x60000147f2f0 UIView:0x7f897ea24a00.bottom == SampleTest.MemesTableViewCell:0x7f897ea2aaf0.bottom   (active)>",
    "<NSLayoutConstraint:0x60000147f570 V:|-(10)-[UIImageView:0x7f897ea18170]   (active, names: '|':UIView:0x7f897ea24a00 )>",
    "<NSLayoutConstraint:0x60000147f110 UIImageView:0x7f897ea18170.height == 80   (active)>",
    "<NSLayoutConstraint:0x60000147eb70 UIImageView:0x7f897ea18170.bottom == UIView:0x7f897ea24a00.bottom - 20   (active)>",
    "<NSLayoutConstraint:0x60000147f4d0 'UIView-Encapsulated-Layout-Height' SampleTest.MemesTableViewCell:0x7f897ea2aaf0.height == 44   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000147f110 UIImageView:0x7f897ea18170.height == 80   (active)>

我的代码:

import UIKit

class MemesTableViewCell : UITableViewCell {
    
    var contentHolderView : UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()
    
    private let nameLabel = UILabel()
    var memeImageView = UIImageView()
    
    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() {
        contentHolderView.backgroundColor = UIColor.red

        addSubview(contentHolderView)

        
        contentHolderView.addSubview(nameLabel)
        contentHolderView.addSubview(memeImageView)
        nameLabel.translatesAutoresizingMaskIntoConstraints = false
        memeImageView.translatesAutoresizingMaskIntoConstraints = false
        memeImageView.contentMode = .scaleAspectFit
        
        
        NSLayoutConstraint.activate([
            //layout contentView
            contentHolderView.topAnchor.constraint(equalTo: self.topAnchor,constant: 0),
            contentHolderView.bottomAnchor.constraint(equalTo: bottomAnchor,constant: 0),
            contentHolderView.leadingAnchor.constraint(equalTo: leadingAnchor,constant: 0),
            contentHolderView.trailingAnchor.constraint(equalTo: trailingAnchor,constant: 0),
            
            memeImageView.topAnchor.constraint(equalTo: contentHolderView.topAnchor, constant: 10),
            memeImageView.leadingAnchor.constraint(equalTo: contentHolderView.leadingAnchor, constant: 10),
            memeImageView.widthAnchor.constraint(equalToConstant: 80),
            memeImageView.heightAnchor.constraint(equalToConstant: 80),
            nameLabel.leadingAnchor.constraint(equalTo: memeImageView.trailingAnchor, constant: 10),
            nameLabel.topAnchor.constraint(equalTo: contentHolderView.topAnchor, constant: 12)
        ])

        
        if let lastView = contentHolderView.getTheLastAddedView() {
            
            lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20).isActive = true
        }
        
        self.layoutIfNeeded()
    }
    

}




extension UIView {
    
    func getTheLastAddedView()->UIView?{
        if let lastView = self.subviews.last{
            return lastView
        }
        return nil
    }
    
    
}

我想知道如何修复此警告?

这是使用带有嵌入视图的单元格时的常见情况。

如您所见,UI 结果 看起来 很好——因为 auto-layout 将 尝试通过打破约束来恢复,然后是 re-establishes 约束。

要消除警告,请为最终定义高度的约束赋予 less-than-required 优先级。

因此,将 setupView() 函数的末尾更改为:

    if let lastView = contentHolderView.getTheLastAddedView() {
        let c = lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20)
        c.priority = .required - 1
        c.isActive = true
        //lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20).isActive = true
    }
    
    // this is not needed
    //self.layoutIfNeeded()

附带说明一下,不应将单元格的子视图添加到或限制到单元格本身。您应该改用单元格的 .contentView

    contentView.addSubview(contentHolderView)

然后:

    NSLayoutConstraint.activate([
        //layout contentView
        contentHolderView.topAnchor.constraint(equalTo: contentView.topAnchor,constant: 0),
        contentHolderView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,constant: 0),
        contentHolderView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 0),
        contentHolderView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: 0),