UIView Auto Layout life cycle
Steps overview

當開啟autolayout的UIView,都會經歷下列生命週期。
init, update, layout, render。
不絕對是單一方向,任何step都可以觸發先前的step,甚至可以強制重新整個life cycle。
Update step
系統會由上而下去呼叫每個subview的updateConstraints()。
基本上,這個step是自動被執行的,但有時候會希望可以手動觸發這個step。
例如,當使用者改變app某個狀態時,會希望畫面產生變化,這時候就要手動觸發這個step。
手動觸發的做法
setNeedsUpdateConstraints,會讓目前constraints無效,然後在下一個cycle更新constraints。
updateConstraintsIfNeeded,會觸發updateConstraints()這個method。
Layout step
系統會由下而上去呼叫superview的layoutSubviews。
layoutSubviews是整個life cycle中最常見到被overridden的方法。
當constraints無法滿足去呈現一個畫面時。
手動計算frames。
基本上,layoutSubviews也可以手動被觸發。
setNeedsLayout,會讓目前view’s layout無效,然後在下一個cycle更新layout。
layoutIfNeeded,會觸發layoutSubviews()這個method。
在overridden layoutSubviews時,需要特別注意下列事項。
別忘記執行super.layoutSubviews()。
千萬別呼叫setNeedsLayout,setNeedsUpdateConstraints,不然會造成無限迴圈。
目前這個view所在hierarchy以外的其他view,不要去改動其constraints。
如果要改動這個view所在hierarchy的其他view(parent or child),千萬要小心,有可能觸發其他view的update,而導致無限迴圈。
Rendering
UIView會將目前需要呈現pixel的工作交給CALayer進行處理。
Rendering step是獨立,不管是否有開啟auto layout。
除非你是在進行一些客製化的繪製OpenGL ES, Core Graphics or UIKit drawing,不然通常不會去overridden drawRect。
What about UIViewControllers
在vc的生命週期中,也有相對應的method,讓vc知道目前畫面在constraint update或view Layout是否已經完成。
Update phase: updateViewConstraints
Layout phase: viewWillLayoutSubviews / viewDidLayoutSubviews
其中viewDidLayoutSubviews是最重要,也最常被overridden。
通知vc目前所有view已經完成layout step了。
這也是最好時機,進行畫面的最後更新,例如改顏色,改frame等。
過了viewDidLayoutSubviews,最後的畫面就會呈現給使用者。
Intrinsic Content Size
透過overridden intrinsicContentSize,來回傳適合目前content的view大小。
If a view has an intrinsic size only for one dimension, you should still override intrinsicContentSize and return UIViewNoIntrinsicMetric for the unknown dimension
Alignment Rectangle
alignmentRect(forFrame:), frame(forAlignmentRect:) 实现这些方法来重写视图与其他视图的对齐方式。

同樣要將兩個圓形帶有陰影的image進行置中,會發現左邊沒辦法置中。
因為左邊的image的陰影是放在image裡面,而右邊的image的陰影是另外用程式來產生的。

The key to understanding their positioning is the difference in alignment rectangles. Since shadow is a part of the left view’s image, it is also a part of its alignment rectangle. Thus, the center of alignment rectangle does not match with the circle center.
Last updated