簡體   English   中英

嵌套的控制器+視圖,以編程方式添加約束,在哪里放置? 最佳實踐?

[英]Nested controllers + views, programmatically adding constraints, which place ? best practice?

我對布局約束/最佳實踐有多個疑問...

摘要

  1. 我想了解最佳實踐以及可能的一些解釋,在何處實例化引用父視圖部分的約束。 我看到viewDidLoad不好
  2. viewDidLoad的哪些替代方法有意義
  3. 而且還有放置位置或設置位置,以便在旋轉更新時調用它(某些常數值是基於給定寬度和元素數量的復雜計算,因此我需要重新計算)
  4. 我是否需要將所有約束保存在屬性中並在更新時引用它們,還是可以self.view.leadingAnchor.constraint(equalTo: parentController.view.leadingAnchor,[..])調用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 = trueview.anchor.constraint(

我首先了解了NSLayoutConstraint,然后了解了其他方式(錨和可視格式語言),現在我混合了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) {}

蘋果還建議使用錨,因為它會自動將約束添加到適當的父對象,並使用NSLayoutConstraint.activate([-,-,-,])激活許多約束,而不是在每個對象上都添加.active = true

問題可能是在menuOneViewController的視圖添加到menuViewController的視圖之前調用了viewDidLoad() 這就是為什么得到...because they have no common ancestor運行時錯誤。

更大的問題和解決方案是,子menuOneViewController不應該知道該子menuOneViewController約束的視圖。這不僅會降低組件menuOneViewController的可重用性,而且還會使將來的調試更加困難。 在將mainOneViewController的視圖添加為子視圖之后,應在menuViewController中設置約束。 另外,使用NSLayoutConstraint.activate(_:)以及.constraint(equalTo:)不帶constant:參數),可以節省一些空間。

這是menuViewControllerviewDidLoad()重寫:

override func viewDidLoad() {
    super.viewDidLoad()

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

    menuOneViewController.parentController = self

    self.view.addSubview(menuOneViewController.view)

    let subView = menuOneViewController.view
    NSLayoutConstraint.activate(constraints: [
        subView.heightAnchor.constraint(equalToConstant: menuRowHeight),
        subView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor)
        subView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
        subView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: -menuRowHeight)
    ]
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM