如何创建一个内部带有子视图的自定义 UIView,并以编程方式使用 AutoLayout 设置其 size/position?

How to create a custom UIView with a subview inside, setting its size/position with AutoLayout programmatically?

我想创建一个自定义 UIView,比如说 TestLabelView,它包含一个边距为 16px 的标签。

看起来像这样:

以下是我尝试创建此自定义 UIView 并在视图控制器中实例化它的方法:

TestLabelView

class TestLabelView: UIView {
    private var label = UILabel()
    
    var text: String = "" { didSet { updateUI() } }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        internalInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        internalInit()
    }
    
    private func internalInit() {
        backgroundColor = .red
        label.numberOfLines = 0
        translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
    }
    
    private func updateUI() {
        label.text = text
        NSLayoutConstraint(item: label,
                           attribute: .leading,
                           relatedBy: .equal,
                           toItem: self,
                           attribute: .leading,
                           multiplier: 1,
                           constant: 24).isActive = true
        NSLayoutConstraint(item: self,
                           attribute: .trailing,
                           relatedBy: .equal,
                           toItem: label,
                           attribute: .trailing,
                           multiplier: 1,
                           constant: 24).isActive = true
        NSLayoutConstraint(item: label,
                           attribute: .top,
                           relatedBy: .equal,
                           toItem: self,
                           attribute: .top,
                           multiplier: 1,
                           constant: 24).isActive = true
        NSLayoutConstraint(item: self,
                           attribute: .bottom,
                           relatedBy: .equal,
                           toItem: label,
                           attribute: .bottom,
                           multiplier: 1,
                           constant: 24).isActive = true
        setNeedsUpdateConstraints()
    }
}

ViewController

class ViewController: UIViewController {
    @IBOutlet weak var testLabelView: TestLabelView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        testLabelView?.text = "This is a test view with a test label, contained in multiple lines"
    }
}

在情节提要中

我设置了placeholder intrinsic size来去除storyboard错误,bottom margin大于等于24px,所以view height要根据content size设置

但是这样做后,我没有看到标签出现。我做错了什么?

感谢您的帮助

您可以为您的 TestLabelView 视图尝试此代码

class TestLabelView: UIView {
    private var label : UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        l.numberOfLines = 0
        return l
    }()
    
    var text: String = "" { didSet { self.label.text = self.text } }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        internalInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        internalInit()
    }
    
    private func internalInit() {
        backgroundColor = .red
        translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        setConstraints()
    }
    
    private func setConstraints() {
        NSLayoutConstraint.activate([
            self.label.topAnchor.constraint(equalTo: self.topAnchor, constant: 16),
            self.label.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 16),
            self.label.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -16),
            self.label.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -16),
        ])
    }
}