是否有一种简短的方法可以将一个视图的所有锚点分配给另一个视图的所有锚点

Is there a short way to assign all the anchors of a view equals to another view's all anchors

假设我有一个容器视图,它有一个 imageView 和 blurEffectView 作为它的子视图。简而言之,我在容器视图内的这张图片上应用了 blurEffect。

我在没有 IB 的情况下使用锚点以编程方式配置自动布局。而imageViewblurredEffectView的anchors和它们的container view完全一样

我想知道是否有 simple/quick 方法来做 aView.allAnchors.equals(bView's allAnchors) 之类的事情?这样我们就可以省去很多重复的代码了。

- container
  - imageView
  - blurEffectView  
    let container: UIView = {
        let aView = UIView()
        aView.translatesAutoresizingMaskIntoConstraints = false
        return aView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        navigationController?.navigationBar.prefersLargeTitles = true
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        configureLayout()
    }
    
    func configureLayout() {
        
        let imageView = UIImageView(image: UIImage(named: "Wang Fei"))
//        imageView.frame = container.bounds
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFit
        container.addSubview(imageView)

        let blurEffect = UIBlurEffect(style: .dark)
        let blurredEffectView = UIVisualEffectView(effect: blurEffect)
        blurredEffectView.translatesAutoresizingMaskIntoConstraints = false
//        blurredEffectView.frame = imageView.bounds
        container.addSubview(blurredEffectView)
        
        view.addSubview(container)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            container.topAnchor.constraint(equalTo: view.topAnchor),
            container.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            container.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            container.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.42),
            
            imageView.leadingAnchor.constraint(equalTo: container.leadingAnchor),
            imageView.trailingAnchor.constraint(equalTo: container.trailingAnchor),
            imageView.topAnchor.constraint(equalTo: container.topAnchor),
            imageView.bottomAnchor.constraint(equalTo: container.bottomAnchor),
            
            blurredEffectView.leadingAnchor.constraint(equalTo: container.leadingAnchor),
            blurredEffectView.trailingAnchor.constraint(equalTo: container.trailingAnchor),
            blurredEffectView.topAnchor.constraint(equalTo: container.topAnchor),
            blurredEffectView.bottomAnchor.constraint(equalTo: container.bottomAnchor)
        ])
    }

没有内置快捷方式。所以大多数人写一个。或者他们采用提供此类捷径的现有框架; SnapKit 是一个受欢迎的选择。

您可以使用框架而不是约束。另外,在viewDidLayoutSubviews里面的代码设置constraint和view也不是什么好办法。另外,使用惰性。

这是可能的解决方案。

class TestViewController: UIViewController {
    private lazy var container: UIView = {
        let aView = UIView()
        aView.translatesAutoresizingMaskIntoConstraints = false
        return aView
    }()

    
    private lazy var imageView: UIImageView = {
        let imageView = UIImageView(image: UIImage(named: "Red"))
        imageView.translatesAutoresizingMaskIntoConstraints = true
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()
    
    private lazy var blurredEffectView: UIVisualEffectView = {
        let blurEffect = UIBlurEffect(style: .dark)
        let blurredEffectView = UIVisualEffectView(effect: blurEffect)
        blurredEffectView.translatesAutoresizingMaskIntoConstraints = false
        return blurredEffectView
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        navigationController?.navigationBar.prefersLargeTitles = true
        setViews()
    }

    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.imageView.frame = container.bounds
        self.blurredEffectView.frame = container.bounds
    }
    
    private func setViews() {
        view.addSubview(container)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            container.topAnchor.constraint(equalTo: view.topAnchor),
            container.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            container.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            container.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.42)])
        
        container.addSubview(imageView)
        container.addSubview(blurredEffectView)
    }
}

您可以像这样将重复代码包裹在方便的 extension 中 -

import UIKit

extension UIView {
    func setUpEdgeToEdge(in container: UIView, insets: UIEdgeInsets = .zero) {
        NSLayoutConstraint.activate([
            self.topAnchor.constraint(equalTo: container.topAnchor, constant: insets.top),
            self.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: insets.left),
            self.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: insets.bottom),
            self.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -insets.right),
        ])
    }
}

现在你可以这样称呼它了-

imageView.setUpEdgeToEdge(in: container)

// OR

imageView.setUpEdgeToEdge(in: container, insets: UIEdgeInsets(top: 10, left: 16, bottom: 10, right: 16))