关于布局限制/锚点最佳做法,我有多个问题……
摘要
self.view.leadingAnchor.constraint(equalTo: parentController.view.leadingAnchor,[..])
我的设置
在我的代码中,我有一个这样的嵌套层次结构
rootController
view
menuViewController
view
menuOneViewController
view
UIButton1
UIButton2
...
UIButton6
每个级别在其父级别的锚点方面都有限制。
我首先在每个Controller的viewDidLoad方法中添加约束。
menuViewController:
override func viewDidLoad() {
super.viewDidLoad()
self.menuOneViewController = MenuOneViewController()
guard let menuOneViewController = self.menuOneViewController else { return }
menuOneViewController.parentController = self
self.view.addSubview(menuOneViewController.view)
}
menuOneViewController:
override func viewDidLoad() {
super.viewDidLoad()
guard let parentController = self.parentController else { return }
let menuRowHeight = parentController.menuRowHeight
self.view.heightAnchor.constraint(equalToConstant: menuRowHeight).isActive = true
self.view.leadingAnchor.constraint(equalTo: parentController.view.leadingAnchor, constant: 0).isActive = true
self.view.trailingAnchor.constraint(equalTo: parentController.view.trailingAnchor, constant: 0).isActive = true
self.view.topAnchor.constraint(equalTo: parentController.view.topAnchor, constant: -(menuRowHeight)).isActive = true
通过此设置,我收到以下消息:
'Unable to activate constraint with anchors
<NSLayoutXAxisAnchor:0x600001199900 "UIView:0x7fd99e705b90.leading">
and <NSLayoutXAxisAnchor:0x600001199980 "UIView:0x7fd99e526bc0.leading">
because they have no common ancestor. Does the constraint or its
anchors reference items in different view hierarchies? That's illegal.'
我的想法和详细信息
我想我明白了……我想在viewDidLoad方法中还没有建立层次结构。我猜想它发生在viewDidLoad()之后,所以我要么需要将这些约束移到viewDidLoad之后调用的子方法中,要么可以在addSubview调用之后在父方法中创建约束。
现在,尽管后一种方法肯定可以工作,但我仍然想知道我通常会把它放在哪个地方。而且,我也不想让子视图控制器视图应该有多大的逻辑困扰父视图控制器。
那我可以将这样的代码放在updateViewConstraints
中吗?因为如果这样的话,轮换似乎没有调用它,这是我接下来要关心的问题,还是我需要设置一些标志或执行某项操作。手动触发。如果是这样,哪种方法?在什么级别?
如果该方法将被调用两次,由于重复的约束生成/重复的约束冲突,我是否会遇到问题?在这种情况下,最佳做法是什么?
在这方面,如果我使用NSLayoutConstraint(item: view, [..]).isActive = true
和view.anchor.constraint(
我首先了解了NSLayoutConstraint,然后了解了其他方式(锚和可视格式语言),现在我混合了anchor.constraints和NSLayoutConstraint,不确定该走哪条路。但是,由于我喜欢干净的代码,所以我想坚持一种方法。
答案 0 :(得分:1)
首先要添加子级VC
addChildViewController(child)
view.addSubview(child.view)
child.view.translatesAutoresizingMaskIntoConstraints = false
// set constraints here
child.didMove(toParentViewController: self)
第二 viewDidLoad
是最好的选择,因为旋转会在设备旋转时自动调整自身的布局,但是如果您要进行调整,请将其设置为var约束,在内部
func viewWillTransition(to size: CGSize,
with coordinator: UIViewControllerTransitionCoordinator) {}
Apple 也建议使用锚点,因为它会自动将约束添加到适当的父级,并使用NSLayoutConstraint.activate([-,-,-,])
激活许多约束,而不是在每个约束上都放置.active = true
>
答案 1 :(得分:1)
问题可能是在将viewDidLoad()
的视图添加到menuOneViewController
的视图之前调用了menuViewController
。这就是为什么您遇到...because they have no common ancestor
运行时错误的原因。
更大的问题和解决方案是,孩子不应该知道该对象受其约束的视图。这不仅会降低组件menuOneViewController
的可重用性,还会使调试变得更加困难在将来。在将menuViewController
的视图添加为子视图之后,应在mainOneViewController
中设置约束。另外,您可以使用NSLayoutConstraint.activate(_:)
和不使用constant:
参数的.constraint(equalTo:)
来节省一些空间。
这是viewDidLoad()
的{{1}}替代:
menuViewController