Auto Layout的生命周期
Auto Layout 不只有布局算法 Cassowary,還包含了布局在運(yùn)行時(shí)的生命周期等一整套布局引擎系統(tǒng),用來(lái)統(tǒng)一管理布局創(chuàng)建、更新和銷(xiāo)毀。這套系統(tǒng)叫做Layout Engine
Auto Layout布局流程

關(guān)于Auto Layout的布局流程,Apple給出圖示如上:即Layout Cycle是一個(gè)在App運(yùn)行循環(huán)RunLoop下循環(huán)執(zhí)行的一個(gè)過(guò)程。
App啟動(dòng)后開(kāi)啟RunLoop,循環(huán)檢測(cè)圖層樹(shù)中是否存在約束變化;
當(dāng)發(fā)生Constrints Change(直接or間接設(shè)置、更新、移除約束),RunLoop檢測(cè)到約束變化;
RunLoop發(fā)現(xiàn)約束變化后,就會(huì)進(jìn)入Deferred Layout階段,視圖的位置、尺寸值會(huì)在這個(gè)過(guò)程計(jì)算,設(shè)置到對(duì)應(yīng)視圖上,并繪制出來(lái);
執(zhí)行完一輪布局,RunLoop會(huì)繼續(xù)檢查視圖樹(shù)的約束更新情況,當(dāng)再次發(fā)現(xiàn)約束更新,則執(zhí)行新一輪布局……
Constraints Change (約束變化)
Constraints Change過(guò)程包括兩個(gè)步驟:約束更新;Layout Engine重新計(jì)算布局,獲取到布局后調(diào)用superview.setNeedLayout(),然后進(jìn)入Deferred Layout Pass。
Deferred Layout Pass (延遲布局)
Deferred Layout Pass 分為兩步:
- 更新約束:從下往上(子視圖到父視圖),依次遍歷視圖層級(jí),調(diào)用View的
updateConstraints方法(或ViewController的updateViewConstraints方法)來(lái)更新約束(你可以在此覆蓋本方法來(lái)設(shè)置自定義約束,且在此設(shè)置時(shí),執(zhí)行效率最高。記得最后調(diào)用父類(lèi)實(shí)現(xiàn))。 - 給視圖及子視圖重新設(shè)定位置(給view的frame賦值):從上到下依次調(diào)用View的layoutSubViews方法(或ViewController的viewLayoutSubViews方法),從Layout Engine中取出預(yù)算好的frame進(jìn)行賦值(你可以覆蓋此方法實(shí)現(xiàn)自定義布局,不過(guò)此刻不是穩(wěn)態(tài),需要在適合時(shí)候調(diào)用父類(lèi)實(shí)現(xiàn))。
延遲布局的觸發(fā)條件
setNeedsUpdateConstraints 下一次loop執(zhí)行updateConstraints
updateConstraintsIfNeeded 立即執(zhí)行updateConstraints
setNeedsLayout 下一次loop執(zhí)行l(wèi)ayoutSubViews
layoutIfNeeded 立即執(zhí)行l(wèi)ayoutSubViews
setNeedDisplay 下一次loop執(zhí)行draw
view的改變會(huì)調(diào)用哪些方法
- 改變
frame.origin不會(huì)掉用layoutSubviews - 改變
frame.size會(huì)使superVIew的layoutSubviews調(diào)用 - 改變
bounds.origin和bounds.size都會(huì)調(diào)用superView和自己view的layoutSubviews方法
參考鏈接:https://github.com/ming1016/study/wiki/深入剖析Auto-Layout,分析iOS各版本新增特性