将框架绑定到 superview 边界 UIView 扩展

Bind frame to superview bounds UIView extension

我经常发现自己在写这些代码行:

myView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    myView.topAnchor.constraint(equalTo: myView.superview.topAnchor),
    myView.bottomAnchor.constraint(equalTo: myView.superview.bottomAnchor),
    myView.leadingAnchor.constraint(equalTo: myView.superview.leadingAnchor),
    myView.trailingAnchor.constraint(equalTo: myView.superview.trailingAnchor)
])

所以我想写一个扩展。像这样:

extension UIView {
    func bindFrameToSuperviewBounds() {
        self.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            self.topAnchor.constraint(equalTo: self.superview.topAnchor),
            self.bottomAnchor.constraint(equalTo: self.superview.bottomAnchor),
            self.leadingAnchor.constraint(equalTo: self.superview.leadingAnchor),
            self.trailingAnchor.constraint(equalTo: self.superview.trailingAnchor)
        ])
    }
}

我的问题:

理论上为什么?因为在实践中它绝对不等价。这种替代技术从未给我带来我期望看到的结果。结果几乎无法预测。

回复评论:

其中:
绿色(外部)矩形是一个 containerView (UIView)。
紫色(内部)矩形是我插入的 UIStackView。
如您所见,约束方法效果很好。

下一个是自动调整掩码方法的结果:

为什么是三张图片?
因为每次新启动应用程序的结果都不一样!

这两种技术产生相同的行为:

extension UIView {
    func bindFrameToSuperviewBoundsWithConstraints() {
        translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            topAnchor.constraint(equalTo: superview!.topAnchor),
            bottomAnchor.constraint(equalTo: superview!.bottomAnchor),
            leadingAnchor.constraint(equalTo: superview!.leadingAnchor),
            trailingAnchor.constraint(equalTo: superview!.trailingAnchor)
        ])
    }

    func bindFrameToSuperviewBoundsWithAutoResizingMask() {
        translatesAutoresizingMaskIntoConstraints = true
        frame = superview!.bounds
        autoresizingMask = [.flexibleWidth, .flexibleHeight]
    }
}

考虑:

class ViewController: UIViewController {
    @IBOutlet weak var containerView: UIView!

    weak var timer: Timer?

    deinit {
        timer?.invalidate()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        containerView.clipsToBounds = false

        let blueView = UIView()
        blueView.backgroundColor = .blue
        containerView.addSubview(blueView)
        blueView.bindFrameToSuperviewBoundsWithConstraints()

        let redView = UIView()
        redView.backgroundColor = .red
        containerView.addSubview(redView)
        redView.bindFrameToSuperviewBoundsWithAutoResizingMask()

        // toggle between the red and blue views

        blueView.isHidden = true

        Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
            redView.isHidden = !redView.isHidden
            blueView.isHidden = !blueView.isHidden
        }
    }
}

这会产生两个交替的子视图,每个子视图使用不同的技术,说明它们的帧是相同的:

如果您发现自动调整掩码解决方案产生的结果与约束方法产生的结果不同,则一定有其他原因。

您好,您可以使用这样的扩展程序:

func constraint(to view: UIView, padding: CGFloat = 0) {
    self.translatesAutoresizingMaskIntoConstraints = false
    self.topAnchor.constraint(equalTo: view.topAnchor, constant: padding).isActive = true
    self.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -padding).isActive = true
    self.leftAnchor.constraint(equalTo: view.leftAnchor, constant: padding).isActive = true
    self.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -padding).isActive = true

并与另一个为 superview 创建快捷方式:

func constraintToSuperview(padding: CGFloat = 0) {
    guard let superview = self.superview else {
        return
    }
    
    self.constraint(to: superview, padding: padding)
}