我有一個簡單的父視圖控制器,我正在向它添加一個子視圖控制器。這是父母:
class ParentViewController: UIViewController {
private var childViewController: ChildViewController!
override func viewDidLoad() {
super.viewDidLoad()
childViewController = ChildViewController()
addChild(childViewController)
view.addSubview(childViewController.view)
childViewController.didMove(toParent: self)
NSLayoutConstraint.activate([
childViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100),
childViewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 50),
childViewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -50),
childViewController.view.heightAnchor.constraint(equalToConstant: 100)
])
}
}
子視圖控制器宣告如下:
class ChildViewController: UIViewController {
private let label1: UILabel = {
let label = UILabel()
label.text = "First label"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let label2: UILabel = {
let label = UILabel()
label.text = "Second label"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemYellow
view.translatesAutoresizingMaskIntoConstraints = false
setupSubViews()
}
private func setupSubViews() {
view.addSubview(label1)
view.addSubview(label2)
print("view.frame.size: \(view.frame.size)")
NSLayoutConstraint.activate([
label1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8),
label1.centerYAnchor.constraint(equalTo: view.topAnchor, constant: self.view.frame.size.height * (1/3)),
label2.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8),
label2.centerYAnchor.constraint(equalTo: view.topAnchor, constant: self.view.frame.size.height * (2/3)),
])
}
}
運行代碼會產生以下結果:

這兩個標簽的位置顯然不是我想要的。我在子視圖控制器中嘗試做的是使用子視圖控制器的視圖在父視圖控制器中定位后的高度為兩個標簽定義 centerYAnchor 約束。如果我在子視圖控制器中列印出view.frame.sizeinside of的值,setupSubViews()則視圖的大小是整個螢屏(在我的情況下為 428.0 x 926.0)。據推測,這是因為子視圖控制器的視圖尚未完全加載/定位在父視圖控制器視圖中?
So I moved the call to setupSubViews() into viewDidLayoutSubviews() of the child view controller and then the value of view.frame.size is correct (328.0 x 100.0) and the labels are positioned correctly within the child view controller's view. But I do see viewDidLayoutSubviews() being called multiple times, though, so I'm wondering if that's really the "correct" lifecycle method for declaring constraints like this? I've seen some people suggest using a boolean to ensure that the constraint code only runs once but I'm not sure that's the right way to handle this situation either.
uj5u.com熱心網友回復:
每當視圖的高度發生變化時,您以這種方式創建的約束必須更新,這可能會發生多次。發生這種情況時,viewDidLayoutSubviews會被呼叫。所以將更新約束的常量的代碼放在 中并沒有什么不妥viewDidLayoutSubviews,因為它被多次呼叫。您不想僅在視圖高度第一次更改時設定約束常量,對嗎?
不過,請注意,您應該只更新約束的常量viewDidLayoutSubviews,而不是setupSubview在那里呼叫。您應該呼叫setupSubviewin loadView,而不是viewDidLoad,因為您正在以編程方式構建視圖。請參閱loadView 和 viewDidLoad 有什么區別?
事實上,這樣做會更好。您可以使用乘數將標簽的中心 Y 約束到視圖的中心 Y,而不是使約束保持不變。標簽 1 的乘數為 2/3,標簽 2 的乘數為 4/3。這將使它們分別距視圖頂部的三分之一和三分之二,
NSLayoutConstraint(
item: label1,
attribute: .centerY,
relatedBy: .equal,
toItem: view,
attribute: .centerY,
multiplier: 2/3,
constant: 0),
NSLayoutConstraint(
item: label2,
attribute: .centerY,
relatedBy: .equal,
toItem: view,
attribute: .centerY,
multiplier: 4/3,
constant: 0),
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/437384.html
