iOS 渲染框架
UIKit
是iOS開發最常用的框架,可以通過設定 UIKit
元件的佈局以及相關屬性來繪製介面。
事實上, UIKit
自身並不具備在螢幕成像的能力,其主要負責對使用者操作事件的響應( UIView
繼承自 UIResponder
),事件響應的傳遞大體是經過逐層的 檢視樹 遍歷實現的。
Core Animation
Core Animation
源自於 Layer Kit
,動畫只是 Core Animation
的冰山一角。 Core Animation
是一個複合引擎,其職責是 儘可能快地組合螢幕上不同的可視內容,這些可視內容可被分解成獨立的圖層(即CALayer),這些圖層會被儲存在一個叫做圖層樹的體系之中 。從本質上而言, CALayer
是使用者所能在螢幕上看見的一切的基礎。
Core Graphics
Core Graphics
基於 Quartz
高階繪圖引擎,主要用於執行時繪製圖像。開發者可以使用此框架來處理基於路徑的繪圖,轉換,顏色管理,離屏渲染,圖案,漸變和陰影,影象資料管理,影象建立和影象遮罩以及PDF文件建立,顯示和分析。
當開發者需要在執行時建立影象時,可以使用 Core Graphics
去繪製。與之相對的是執行前建立影象,例如用Photoshop提前做好圖片素材直接匯入應用。相比之下,我們更需要 Core Graphics
去在執行時實時計算、繪製一系列影象幀來實現動畫。
Core Image
Core Image
與 Core Graphics
恰恰相反, Core Graphics
用於在執行時建立影象,而 Core Image
用於處理執行前建立的影象。 Core Image
框架擁有一系列現成的影象過濾器,能對一寸照的影象進行高效的處理。
大部分情況下, Core Image
會在GPU中完成工作,如果GPU忙,會使用CPU進行處理。
OpenGL ES
OpenGL ES
是 OpenGL
的子集。在圖形渲染原理一文中提到過 OpenGL
是一套第三方標準,函式的內部實現由對應的GPU廠商開發實現。
UIView與CALayer的關係
CALayer
事實上是使用者所能在螢幕上看見的一切的基礎。為什麼 UIKit
中的檢視能夠呈現視覺化內容,就是因為 UIKit
中的每一個UI檢視控制元件其實內部都有一個關聯的 CALayer
,即 backing layer
。
由於這種一一對應的關係,檢視層級有用 檢視樹 的樹形結構,對應 CALayer
層級也擁有 圖層樹 的樹形結構。
其中,檢視的職責是建立並管理圖層,以確保當子檢視在層級關係中新增或被移除時,其關聯的圖層在圖層樹中也有相同的操作,即保證檢視樹和圖層樹在結構上的一致性。
為什麼iOS要基於UIView和CALayer提供兩個平行的層級關係呢?
其原因在於要做 職責分離 ,這樣也能避免很多重複程式碼。在iOS和Mac OSX兩個平臺上,事件和使用者互動有很多地方的不同,基於多點觸控的使用者介面和基於滑鼠鍵盤的互動有著本質的區別,這就是為什麼iOS有 UIKit
和 UIView
,對應Mac OSX有 AppKit
和 NSView
的原因。它們在功能上很相似,但是在實現上有著顯著的區別。
實際上,這裡並不是兩個層級關係,而是四個。每一個都扮演著不同的角色。除了 檢視樹 和 圖層樹 ,還有 呈現樹 和 渲染樹 。
CALayer
那麼為什麼 CALayer
可以呈現視覺化內容呢?因為 CALayer
基本等同於一個 紋理 。紋理是GPU進行影象渲染的重要依據。
在圖形渲染原理中提到紋理本質上就是一張圖片,因此 CALayer
也包含一個 contents
屬性指向一塊快取區,稱為 backing store
,可以存放點陣圖(Bitmap)。iOS中將該快取區儲存的圖片稱為 寄宿圖 。

圖形渲染流水線支援從頂點開始進行繪製(在流水線中,頂點會被處理生成紋理),也支援直接使用紋理(圖片)進行渲染。相應地,在實際開發中,繪製介面也有兩種方式: 一種是 手動繪製 ;另一種是 使用圖片 。
對此,iOS中也有兩種相應的實現方式:
- 使用圖片: contents image
- 手動繪製: custom drawing
Contents Image
Contents Image
是指通過 CALayer
的 contents
屬性來配置圖片。然而, contents
屬性的型別為 id
,在這種情況下,可以給 contents
屬性賦予任何值,app仍可以編譯通過。但是在實踐中,如果 contents
的值不是 CGImage
,得到的圖層將是空白的。
既然如此,為什麼要將 contents
的屬性型別定義為 id
而非 CGImage
。因為在Mac OS系統中,該屬性對 CGImage
和 NSImage
型別的值都起作用,而在iOS系統中,該屬性只對 CGImage
起作用。
本質上, contents
屬性指向的一塊快取區域,稱為 backing store
,可以存放bitmap資料。
Custom Drawing
Custom Drawing
是指使用 Core Graphics
直接繪製寄宿圖。實際開發中,一般通過繼承 UIView
並實現 -drawRect:
方法來自定義繪製。
雖然 -drawRect:
是一個 UIView
方法,但事實上都是底層的 CALayer
完成了重繪工作並儲存了產生的圖片。 下圖所示為 drawRect:
繪製定義寄宿圖的基本原理

-
UIView
有一個關聯圖層,即CALayer
。 -
CALayer
有一個可選的delegate
屬性,實現了CALayerDelegate
協議。UIView
作為CALayer
的代理實現了CALayerDelegate
協議。 - 當需要重繪時,即呼叫
-drawRect:
,CALayer
請求其代理給予一個寄宿圖來顯示。 -
CALayer
首先會嘗試呼叫-displayLayer:
方法,此時代理可以直接設定contents
屬性。
- (void)displayLayer:(CALayer *)layer; 複製程式碼
- 如果代理沒有實現
-displayLayer:
方法,CALayer
則會嘗試呼叫-drawLayer:inContext:
方法。在呼叫該方法前,CALayer
會建立一個空的寄宿圖(尺寸由bounds
和contentScale
決定)和一個Core Graphics
的繪製上下文,為繪製寄宿圖做準備,作為ctx
引數傳入。
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx; 複製程式碼
- 最後,有
Core Graphics
繪製生成的寄宿圖會存入backing store
。
Core Animation 流水線
介紹一下 Core Animation
流水線的工作原理:

Render Server
程序。
App通過IPC將渲染任務及相關資料提交給 Render Server
。 Render Server
處理完資料後,再傳遞至GPU。最後由GPU呼叫iOS的影象裝置進行顯示。
Core Animation
流水線的詳細過程如下:
- 首先,由app處理事件(Handle Events),如:使用者點選操作,在此過程中app可能需要更新 檢視樹 ,相應地, 圖層樹 也會被更新。
- 其次,app通過CPU完成對顯示內容的計算,如:檢視的建立、佈局計算、圖片解碼、文字繪製等。在完成對現實內容的計算之後,app對圖層進行打包,並在下一次RunLoop時將其傳送至
Render Server
,即完成了一次commit Transaction
操作。 -
Render Server
主要執行OpenGL、Core Graphics相關程式,並呼叫GPU。 - GPU則在物理層上完成了對影象的渲染。
- 最終,GPU通過
Frame Buffer
、視訊控制器等相關部件,將影象顯示在螢幕上。
對上述步驟進行串聯,他們執行所消耗的時間圓圓超過16.67ms,因此為了滿足對螢幕的60FPS重新整理率的支援,需要將這些步驟進行分解,通過流水線的方式並行執行,如下圖:

Commit Transaction
在 Core Animation
流水線中,app呼叫 Render Server
前的最後一步 Commit Transaction
其實可以細分為4個步驟:
Layout Display Prepare Commit
Layout
Layout
階段主要進行檢視構建,包括: LayoutSubviews
方法的過載, addSubview:
方法填充子檢視等。
Display
Display
階段主要進行檢視繪製,這裡僅僅是設定成像的圖元資料。過載檢視的 drawRect:
方法可以自定義 UIView
的顯示,其原理是在 drawRect:
方法內部繪製寄宿圖,該過程使用GPU和記憶體。
Prepare
Prepare
階段屬於附加步驟,一般處理影象的解碼和轉碼等操作。
Commit
commit
階段主要將圖層進行打包,並將它們傳送至 Render Server
。該過程會遞迴執行,因為圖層和檢視都是以樹形結構存在。
動畫渲染原理
iOS動畫的渲染也是基於上述 Core Animation
流水線完成的。這裡我們重點關注app與 Render Server
的執行流程。
日常開發中,如果不是特別的複雜動畫,一般使用 UIView
Animation實現,iOS將其處理過程分為如下三部階段:
animationWithDuration:animations: Layout,Display,Prepare,Commit Render Server

參考部落格iOS影象渲染原理