swift - 为子视图控制器使用自动布局
问题描述
我又遇到了自动布局的问题...
这就是我最终想要得到的:
我正在使用父视图控制器和子视图控制器顶部、中心和底部的代码做所有事情。
最后,我希望能够将顶视图控制器的高度设置为其固有高度——这就是我现在失败的地方......顶视图控制器有一个垂直堆栈视图用于放置元素(到最后能够根据需要添加和删除视图)。
这个实现...
import UIKit
class ParentViewController: UIViewController {
lazy var topChildView: UIView = {
let topView = topChildViewController.view!
topView.backgroundColor = .red
topView.translatesAutoresizingMaskIntoConstraints = false
topView.accessibilityIdentifier = "top"
return topView
}()
lazy var topChildViewController: TopChildViewController = {
let topVC = TopChildViewController()
return topVC
}()
lazy var centerChildView: UIView = {
let centerView = centerChildViewController.view!
centerView.backgroundColor = .blue
centerView.translatesAutoresizingMaskIntoConstraints = false
centerView.accessibilityIdentifier = "center"
return centerView
}()
lazy var centerChildViewController: CenterChildViewController = {
let centerVC = CenterChildViewController()
return centerVC
}()
lazy var bottomChildView: UIView = {
let bottomView = bottomChildViewController.view!
bottomView.backgroundColor = .green
bottomView.translatesAutoresizingMaskIntoConstraints = false
bottomView.accessibilityIdentifier = "bottom"
return bottomView
}()
lazy var bottomChildViewController: BottomChildViewController = {
let bottom = BottomChildViewController()
return bottom
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray
self.addChild(topChildViewController)
self.view.addSubview(topChildView)
self.addChild(centerChildViewController)
self.view.addSubview(centerChildView)
self.addChild(bottomChildViewController)
self.view.addSubview(bottomChildView)
NSLayoutConstraint.activate([
topChildView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12),
topChildView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
topChildView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
topChildView.heightAnchor.constraint(equalToConstant: topChildView.intrinsicContentSize.height),
centerChildView.topAnchor.constraint(equalTo: topChildView.bottomAnchor),
centerChildView.leadingAnchor.constraint(equalTo: topChildView.leadingAnchor),
centerChildView.trailingAnchor.constraint(equalTo: topChildView.trailingAnchor),
bottomChildView.leadingAnchor.constraint(equalTo: topChildView.leadingAnchor),
bottomChildView.trailingAnchor.constraint(equalTo: topChildView.trailingAnchor),
bottomChildView.heightAnchor.constraint(equalToConstant: 100),
bottomChildView.topAnchor.constraint(equalTo: centerChildView.bottomAnchor),
bottomChildView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
])
}
}
class TopChildViewController: UIViewController {
lazy var stackView: UIStackView = {
let s = UIStackView()
s.translatesAutoresizingMaskIntoConstraints = false
s.axis = .vertical
s.distribution = .fillEqually
s.spacing = 6
return s
}()
lazy var textField: UITextField = {
let t = UITextField()
t.borderStyle = .roundedRect
t.placeholder = "Some fancy text"
t.accessibilityIdentifier = "textfield"
t.translatesAutoresizingMaskIntoConstraints = false
return t
}()
lazy var label: UILabel = {
let l = UILabel()
l.accessibilityIdentifier = "label"
l.translatesAutoresizingMaskIntoConstraints = false
l.text = "Awesome Label"
l.textAlignment = .center
return l
}()
override func loadView() {
view = UIView()
view.addSubview(stackView)
stackView.addArrangedSubview(textField)
stackView.addArrangedSubview(label)
NSLayoutConstraint.activate([
textField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12),
textField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
textField.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12)
])
}
}
class CenterChildViewController: UIViewController {
override func loadView() {
view = UIView()
}
}
class BottomChildViewController: UIViewController {
override func loadView() {
view = UIView()
}
}
...导致这个结果:
虽然我知道错误(在我尝试访问它时,内在高度似乎不可用,见下文),但我不知道如何解决它——我错过了什么?
是否需要在其他地方创建约束?我真的很希望能够从父视图控制器控制它......
[LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( "<NSLayoutConstraint:0x600002306d50 top.height == - 1 (active, names: top:0x7f81c1e1f120 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x600002306d50 top.height == - 1 (active, names: top:0x7f81c1e1f120 )> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
解决方案
在玩了一些之后,我确实意识到我必须topChildView.heightAnchor.constraint(equalToConstant: topChildView.intrinsicContentSize.height),
完全省略才能使其工作......
所以我提供的约束ParentViewController.viewDidLoad()
如下:
NSLayoutConstraint.activate([
topChildView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12),
topChildView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
topChildView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
centerChildView.topAnchor.constraint(equalTo: topChildView.bottomAnchor),
centerChildView.leadingAnchor.constraint(equalTo: topChildView.leadingAnchor),
centerChildView.trailingAnchor.constraint(equalTo: topChildView.trailingAnchor),
bottomChildView.leadingAnchor.constraint(equalTo: topChildView.leadingAnchor),
bottomChildView.trailingAnchor.constraint(equalTo: topChildView.trailingAnchor),
bottomChildView.heightAnchor.constraint(equalToConstant: 100),
bottomChildView.topAnchor.constraint(equalTo: centerChildView.bottomAnchor),
bottomChildView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
])
推荐阅读
- entity-framework - 获取两个日期之间的总天数 Linq C#
- node.js - 通过 api 获取谷歌分析报告
- sql-server - 在 SQL Server 中使用 sp_executesql 动态插入到表中
- ios - 翠鸟不显示图像
- php - php 使用获取值的问题。适用于页面的一部分,但不适用于另一部分
- regex - 正则表达式:不允许用户输入使用 0 和 9 形成的重复数字
- javascript - 在 Asp.net Core MVC 中序列化表单并将其转换为复杂类以使用 Ajax 发布整个模型的问题
- python - Python:如何使这段代码变得更好?
- laravel - 如何在laravel中的.env中实例化?
- regex - 为什么 $ 可以匹配两次,给出一个额外的空匹配?