使用過 Auto Layout 的人肯定都遇到過獲取不到真實 frame 的情況,而大部分人經過簡單搜索都能得到一個滿意的解決方案:在想獲取真實 frame 之前調用一下self.view.layoutIfNeeded()
,這是一個能用但是并不好的方法:進行了額外的毫不需要的 frame 計算。
我們從 View Controller 的生命周期來分析這個問題:
viewDidLoad
viewWillAppear
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear
viewWillDisappear
viewDidDisappear
Auto Layout 的布局是從外到內的,即從屏幕尺寸開始布局,一直布局到最里面的細節元素,我們的目光自然地落在了 viewDidLayoutSubviews
和viewDidAppear
上了:
viewDidLayoutSubviews
時當前視圖已經把子元素布局完畢,frame 已經形成
viewDidAppear
時,渲染系統把當前視圖加入父視圖中,顯示在屏幕上
所以,解決方案其實已經水落石出了:
避免調用 layoutSubviews
,在 viewDidLayoutSubviews
和 viewDidAppear
中進行 frame 的獲取
如果你需要盡早地做一些大動作,推薦在 viewDidLayoutSubviews
,此時用戶還沒有看到 UI,用法可以更靈活
注意 viewDidLayoutSubviews
可能會被多次調用,所以添加元素之類的操作盡量避免在這里做
viewDidAppear
中可以干一切你想干的事情,但是一些需要用戶看到的東西例如動畫只能在這里做
更推薦把需要做的事情盡量全部放到 viewDidAppear 中來做,讓用戶盡早地看到界面,這是人機交互的基本原則
回到標題中的問題:什么時候才能獲得正確的 frame? 在 viewDidLayoutSubviews
和 viewDidAppear
中。
原文地址