[英]Force Auto layout to update UIView frame correctly at viewDidLoad
雖然它很簡單,但我仍然發現自己正在努力解決正確的問題。
我試圖了解在使用自動布局時在viewDidLoad
找到REAL UIView
(或任何其他子視圖)幀的正確方法是什么。
主要問題是在viewDidLoad中,視圖未應用其約束。 我知道這種情況的“已知”答案是
override func viewDidLoad() {
super.viewDidLoad()
view.layoutIfNeeded()
stepContainer.layoutIfNeeded() // We need this Subview real frame!
let realFrame = stepContainer.frame
}
但我發現它並不總是有效,並且不時會給出錯誤的幀(即不是顯示的最終幀)。
經過一些研究后,我發現在DispatchQueue.main.async { }
下扭曲此代碼可以得到准確的結果。 但是我不確定這是否是正確的處理方法,或者我是否使用此方法導致了一些引擎蓋下的問題。 最終“工作”代碼:
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
self. stepContainer.layoutIfNeeded()
print(self. stepContainer.frame) // Real frame..
}
}
注意:我只需要從viewDidLoad中找到真正的幀,請不要建議使用viewDidAppear / layoutSubviews等。
正如@DavidRönnqvist指出的那樣
dispatch async給你“正確”值的原因是它被安排在下一個運行循環中運行; 在
viewWillAppear
和viewDidLayoutSubviews
運行之后。
例
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
print("DispatchQueue.main.async viewDidLoad")
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("viewWillAppear")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("viewDidAppear")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("viewDidLayoutSubviews")
}
viewWillAppear中
viewDidLayoutSubviews
viewDidAppear
DispatchQueue.main.async viewDidLoad
來自viewDidLoad
DispatchQueue.main.async
代碼甚至在viewDidAppear
之后調用。 因此,在viewDidLoad
使用DispatchQueue.main.async
會為您提供正確的幀,但它不是最早的幀。
回答
如果你想盡早獲得正確的框架, viewDidLayoutSubviews
是正確的做法。
如果你必須在viewDidLoad
放入一些代碼,那么你正在做正確的方法。 看起來像DispatchQueue.main.async
是最好的方法。
閱讀完評論后,也許您可以嘗試將視圖控制器嵌入另一個帶有容器的視圖控制器中並執行以下操作:
var viewSize : CGSize?
var parentViewSize : CGSize?
viewDidLayoutSubViews
的大小並存儲它: viewSize = view.size
prepareForSegue
發送您存儲的大小: (destinationViewController as? MyViewController)?.parentViewSize = viewSize
viewDidLoad
您將訪問具有良好值的parentViewSize
變量 它會這樣做嗎?
你的問題與這個問題類似,我的回答也是一樣的。
在viewDidLoad中,不保證框架與最終顯示視圖時的框架相同。 UIKit會根據將出現的上下文調整視圖控制器視圖的框架,然后再顯示它。 為了更好地理解視圖生命周期,您可以參考此圖像。
該圖像將幫助您了解代碼的工作原理。 如圖所示,一旦加載了視圖,就會調用viewWillAppear,當你設置dispatch async時,它會在執行viewWillAppear后異步添加到線程中。 因此,一旦調用了viewWillAppear,您的框架就會根據您的視圖進行更新,並且您可以在調度異步中獲得正確的框架。
參考文獻: 圖像源
所以,最后,你可以選擇以下兩種方案之一:
希望這可以幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.