问题描述
我正在尝试以编程方式执行UI,并且遇到了奇怪的约束错误,但是当我运行该应用程序时,它看起来像预期的那样。
我要做什么:
我有一个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()
}