Swift-自动布局约束UIView-Encapsulated-Layout-Width

问题描述

我正在尝试以编程方式执行UI,并且遇到了奇怪的约束错误,但是当我运行该应用程序时,它看起来像预期的那样。

enter image description here

我要做什么:

我有一个ViewController TodayVC,其中有一个UIView,我正在尝试在该视图中呈现MWStepsActivityVC的内容。

这是我的TodayVC:

class TodayVC: UIViewController {
    
    let scrollView = UIScrollView()
    let contentView = UIView()
    
    let stepsActivityView = UIView()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureViewController()
        configureScrollView()
        configureContainerViews()
        layoutUI()
    }
    
    func configureViewController() {
        view.backgroundColor = .systemBackground
    }
    
    func configureScrollView() {
        view.addSubview(scrollView)
        scrollView.addSubview(contentView)
        scrollView.pinToEdges(of: view)
        contentView.pinToEdges(of: scrollView)
        
        NSLayoutConstraint.activate([
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),contentView.heightAnchor.constraint(equalToConstant: 600)
        ])
    }
    
    func configureContainerViews() {
        self.add(childVC: MWStepsActivityVC(activityType: .steps),to: self.stepsActivityView)
    }
    
    func layoutUI() {
        contentView.addSubview(stepsActivityView)
        stepsActivityView.translatesAutoresizingMaskIntoConstraints = false
        
        let padding: CGFloat = 20
        let itemHeight: CGFloat = 140
        
        NSLayoutConstraint.activate([
            stepsActivityView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: padding),stepsActivityView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: -padding),stepsActivityView.topAnchor.constraint(equalTo: contentView.topAnchor,stepsActivityView.heightAnchor.constraint(equalToConstant: itemHeight),])
        
        print("TodayVC view width \(view.frame.size.width)")
    }
    
    func add(childVC: UIViewController,to containerView: UIView) {
        addChild(childVC)
        containerView.addSubview(childVC.view)
        childVC.view.frame = containerView.bounds
        childVC.didMove(toParent: self)
    }
}

UIViewExtension:

extension UIView {
    func addSubviews(_ views: UIView...) {
        for view in views {
            addSubview(view)
        }
    }
    
    func pinToEdges(of superview: UIView) {
        translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            topAnchor.constraint(equalTo: superview.topAnchor),leadingAnchor.constraint(equalTo: superview.leadingAnchor),trailingAnchor.constraint(equalTo: superview.trailingAnchor),bottomAnchor.constraint(equalTo: superview.bottomAnchor),])
    }
}

MWStepsActivityVC:

class MWActivityVC: UIViewController {
    
    let iconImageView = UIImageView()
    let titleLabel = UILabel()
    let counterLabel = UILabel()
    
    init(activityType: ActivityType) {
        super.init(nibName: nil,bundle: nil)
        self.set(activityType: activityType)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureBackgroundView()
        layoutUI()
        placeholderData()
    }
    
    fileprivate func placeholderData() {
        iconImageView.image = SFSymbols.steps
        titleLabel.text = "StepsStepsStepsStepsStepsStepsStepsStepsStepsStepsStepsStepsStepsStepsStepsStepsStepsSteps"
        counterLabel.text = "9000"
        counterLabel.backgroundColor = .red
    }
    
    fileprivate func configureBackgroundView() {
        view.layer.cornerRadius = 18
    }

    
    fileprivate func layoutUI() {
        view.addSubviews(iconImageView,titleLabel,counterLabel)
        iconImageView.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        counterLabel.translatesAutoresizingMaskIntoConstraints = false
        
        let padding: CGFloat = 20
        NSLayoutConstraint.activate([
            iconImageView.topAnchor.constraint(equalTo: view.topAnchor,iconImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor,iconImageView.heightAnchor.constraint(equalToConstant: 20),iconImageView.widthAnchor.constraint(equalToConstant: 20),titleLabel.centerYAnchor.constraint(equalTo: iconImageView.centerYAnchor),titleLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor,titleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor,titleLabel.heightAnchor.constraint(equalToConstant: 20),counterLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor,counterLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor,counterLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor,counterLabel.heightAnchor.constraint(equalToConstant: 40)
        ])
        
        print("MWStepsActivityVC view width \(view.frame.size.width)")
    }
}

我遇到这些错误:

"<NSLayoutConstraint:0x600002228320 H:|-(20)-[UIImageView:0x7fc0abe077a0]   (active,names: '|':UIView:0x7fc0abd10850 )>","<NSLayoutConstraint:0x6000022283c0 UIImageView:0x7fc0abe077a0.width == 20   (active)>","<NSLayoutConstraint:0x600002228460 H:[UIImageView:0x7fc0abe077a0]-(20)-[UILabel:0x7fc0abe08a70]   (active)>","<NSLayoutConstraint:0x6000022284b0 UILabel:0x7fc0abe08a70.trailing == UIView:0x7fc0abd10850.trailing - 20   (active)>","<NSLayoutConstraint:0x600002230b90 'UIView-Encapsulated-Layout-Width' UIView:0x7fc0abd10850.width == 0   (active)>","<NSLayoutConstraint:0x600002228320 H:|-(20)-[UIImageView:0x7fc0abe077a0]   (active,"<NSLayoutConstraint:0x6000022285a0 H:|-(20)-[UILabel:0x7fc0abe08ce0]   (active,"<NSLayoutConstraint:0x6000022285f0 UILabel:0x7fc0abe08ce0.trailing == UIView:0x7fc0abd10850.trailing - 20   (active)>","<NSLayoutConstraint:0x600002230b90 'UIView-Encapsulated-Layout-Width' UIView:0x7fc0abd10850.width == 0   (active)>"

我试图使用wtfautolayout.com网站来了解问题所在,似乎问题出在UIView-Encapsulated-Layout-Width上,它认为将其设置为0,但是当我尝试打印view.frame.size.width时,得到正确的宽度:

MWStepsActivityVC view width 375.0
TodayVC view width 375.0 

有人可以帮我吗?我已经为此苦了一天。

解决方法

最后,我能够修复它。我忘记在主线程上运行configureContainerViews ...

DispatchQueue.main.async {
    self.configureContainerViews()
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...