ios - 嵌套 Controller + View ,以编程方式添加约束,哪个地方?最佳实践?

标签 ios constraints swift4 nslayoutconstraint

我有多个关于布局约束/ anchor 最佳实践的问题...

总结

  1. 我想知道最佳实践和一些解释,在哪里实例化引用父 View 部分的约束。我看到 viewDidLoad 不好
  2. viewDidLoad 的哪些替代方案有意义
  3. 还有放在哪里,或者设置什么,所以它会在旋转更新时被调用(一些常量值是基于给定宽度和元素数量的复杂计算,然后我需要重新计算)
  4. 我是否需要将所有约束保存在属性中并在更新时引用它们,或者我可以调用 self.view.leadingAnchor.constraint(equalTo: parentController.view.leadingAnchor,[..])一遍又一遍

我的设置

在我的代码中,我有一个这样的嵌套层次结构

rootController
view
    menuViewController
    view
        menuOneViewController
        view
            UIButton1
            UIButton2
            ...
            UIButton6

每个级别对其父级别的 anchor 都有限制。

我首先在每个 Controller 的 viewDidLoad 方法中添加约束。

菜单 View Controller :

override func viewDidLoad() {
    super.viewDidLoad()

    self.menuOneViewController = MenuOneViewController()
    guard let menuOneViewController = self.menuOneViewController else { return }

    menuOneViewController.parentController = self

    self.view.addSubview(menuOneViewController.view)
}

菜单单一 View Controller :

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 调用之后在父项中创建约束。

虽然后一种方式肯定有效,但我仍然想知道我通常会把它放在哪个其他地方。而且我也不想用 subview Controller View 应该有多大的逻辑来打扰父 View Controller 。

那么我会把这样的代码放在 updateViewConstraints 中吗?因为如果是这样,它似乎不会被轮换调用,这是我的下一个问题,或者我是否需要设置一些标志或做某事。手动触发。如果是,哪种方法?在哪个级别?

此外,如果该方法将被调用两次,我会因为重复约束生成/重复冲突约束而遇到问题吗?在这种情况下,最佳做法是什么?

同样在这方面,如果我使用 NSLayoutConstraint(item: view, [..]).isActive = trueview.anchor.constraint(

我首先了解了 NSLayoutConstraint,然后了解了其他方式( anchor 和视觉格式语言),现在我混合使用了 anchor.constraints 和 NSLayoutConstraint,但不确定该走哪条路。但是因为我喜欢我的代码干净,所以我想坚持使用一种方式。

最佳答案

首先您应该添加一个子 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 推荐使用 anchor ,因为它会自动将约束添加到适当的 parent ,加上使用 NSLayoutConstraint.activate([-,-,-,]) 来激活许多约束而不是在每个约束上放置 .active = true

关于ios - 嵌套 Controller + View ,以编程方式添加约束,哪个地方?最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52283100/

相关文章:

swift - 使用 Decodable 进行 JSON 解析时,optional 和 decodeIfPresent 有什么区别?

ios - 从 mapAnnotaion 获取对象并使用 segue 传递它

ios - 为显示错误图像的 MKMapView 设置 annotationView 图像

ios - 如何在 Interface Builder NIB 中使用 GLKView 设置 GLKViewController 库对象

python - 如何检查列表中元素之间的约束/这是约束编程吗?

iphone - 如何从UIView中删除约束?

ios - 如果条件 swift ,如何检查零字符串

cocoa - NSTextField 中的 setStringValue 总是会改变高度

swift - 从 ViewController 中的登录到 UITabBarController 的转换

ios - 检查 iPhone Swift 4 中的耳机端口是否可用