1. The Layer Tree
Ogres have layers. Onions have layers. You get it? We both have layers.
——Shrek
Core Animation 的名字很容易引起誤解茂缚,讓大家都認(rèn)為它的主要目的是實(shí)現(xiàn)動(dòng)畫的,實(shí)際上動(dòng)畫只是 Core Animation 框架的功能之一,Core Animation 框架最開始的名字是 Layer kit。
Core Animation 是一個(gè)組裝引擎(compositing engine),它的工作是盡快地將屏幕上的各塊獨(dú)立的內(nèi)容組合起來用來展示尝艘。這些由各獨(dú)立內(nèi)容組合起來的層級結(jié)構(gòu)就是 layer tree。
Layers 和 Views 的關(guān)系:表面上看,UIView 和 CAlayer 一樣幔睬,都是方形的,可以通過疊加組成層級關(guān)系芹扭,可以展示圖片麻顶、文字、顏色等內(nèi)容舱卡,可以管理子層級的位置辅肾,可以執(zhí)行動(dòng)畫;實(shí)際上灼狰,對于 UIView宛瞄,關(guān)于渲染(rendering)、布局(layout)交胚、動(dòng)畫(animation)的這些工作份汗,都不是由 view 自己處理的,而是 layer 處理的蝴簇;唯一一個(gè) CALyer 不能處理而由 UIView 自己處理的任務(wù)是觸摸事件等用戶交互杯活。
每一個(gè) UIView 都有一個(gè)叫做 layer 的 CALayer 屬性。也就是常說的 backing layer熬词,view 的職責(zé)就是創(chuàng)建和管理這個(gè) layer旁钧,來保證當(dāng)添加或移除 subviews 時(shí),layer 層也在添加或移除相應(yīng)的 layer互拾。
實(shí)際上歪今,UIView 在屏幕上的展示和動(dòng)畫都是由 backing layers 來實(shí)現(xiàn)的,UIView 只是一個(gè) CALayer 的簡單的封裝颜矿,只提供一些像觸摸事件響應(yīng)等 iOS 獨(dú)有的功能寄猩,以及一些 Core Animation 底層功能的高級接口。
為什么 iOS 有這兩個(gè)分別基于 UIView 和 CALayer 的并列層級骑疆?為什么不是一個(gè)能夠管理所有任務(wù)的層級田篇?原因就在于分清職責(zé)替废,避免代碼重復(fù)。
在 iOS 和 Mac OS 上泊柬,對事件(event)和用戶交互(user interaction)的處理方式是不同的椎镣;處理手勢操作和處理鼠標(biāo)鍵盤的機(jī)制是不同的,所以 iOS 中有 UIKit 和 UIView兽赁,而 Mac OS 有 AppKit 和 NSView状答,它們的功能很相似,但是實(shí)現(xiàn)方式卻有顯著的差異闸氮。
渲染(rendering)剪况、布局(layout)、動(dòng)畫(animation)這些功能在iPhone蒲跨、iPad等觸屏設(shè)備上和在 MacBook 等非觸屏設(shè)備上是一樣的译断。通過將這些功能相關(guān)的邏輯單獨(dú)分離出來成 Core Animation 框架,Apple 就能夠在 iOS 和 Mac OS 之間共享這些代碼了或悲,這對于Apple 自家的 OS 開發(fā)團(tuán)隊(duì)以及那些要開發(fā)能在兩個(gè)平臺(tái)都能運(yùn)行的 app 的第三方開發(fā)者來說孙咪,事情變得更簡單了。
事實(shí)上巡语,除了 view hierarchy 和 layer tree 這兩個(gè)層級之外翎蹈,還有 presentation tree 和 render tree 另外兩個(gè)層級,這四個(gè)層級男公,每個(gè)層級都扮演著不同的角色荤堪。
如果 CALayer 不過是 UIView 內(nèi)部的具體實(shí)現(xiàn)而已,那我們?yōu)槭裁催€要去了解它枢赔?從某種程度上來講澄阳,我們確實(shí)不需要接觸 CALayer 就可以直接通過 UIView 得高級接口來繪制圖形,實(shí)現(xiàn)動(dòng)畫踏拜。但是碎赢,使用簡單同時(shí)也意味著失去了靈活性,如果你想實(shí)現(xiàn)一些與接口本身所提供的功能不一樣速梗,或者要使用一些 Apple 沒有在 UIView 中暴露出來的接口時(shí)肮塞,你就需要倒騰一下偏底層的 Core Animation 了。
那么姻锁,有什么事情是 CALayer 能做枕赵,而 UIView 做不了的呢?
繪制帶陰影位隶、圓角烁设、邊框的圖形(Drop shadows, rounded corners, and colored borders)
3D 變換(3D transforms and positioning)
不是方形的圖形(Nonrectangular bounds)
視圖內(nèi)容上加一些遮罩(Alpha masking of content)
多步驟動(dòng)畫,非線性動(dòng)畫(Multistep, nonlinear animations)
大多數(shù)情況下,相比直接操作獨(dú)立的 CALayer 對象装黑,用帶有 backing layer 的 UIView 對象來繪制圖形,往往更簡單弓熏,因?yàn)?UIVIew 有一些像 autoresizing恋谭、autolayout、event handling 等 CALayer 沒有的功能挽鞠。
-
只有極個(gè)別情況下疚颊,你應(yīng)該使用獨(dú)立的 CALayer,而不是帶有 backing layer 的 UIView:
- You might be writing cross-platform code that will also need to work on a Mac.
- You might be working with multiple CALayer subclasses and have no desire to create new UIView subclasses to hostthem all.
- You might be doing such performance-critical work that even the negligible overheadof maintaining the extra UIView object makes a measurable difference (although inthat case, you’ll probably want to use something like OpenGL for your drawinganyway).