常用框架
iOS系統(tǒng)下通常使用UIKit西篓、Core Animation锣光、Core Graphics、Core Image蔬浙、Core Video等框架來(lái)完成圖形圖像的渲染和顯示:
UIKit:UIKit是iOS系統(tǒng)中用于創(chuàng)建用戶界面的框架猪落。它提供了許多用于顯示文本、圖像畴博、按鈕等控件的類笨忌,同時(shí)也提供了一些動(dòng)畫效果的支持。
Core Animation:CoreAnimation是一個(gè)動(dòng)畫框架俱病,可以用于創(chuàng)建基于圖層的動(dòng)畫官疲。它提供了一些基本的動(dòng)畫類型,比如位移亮隙、旋轉(zhuǎn)途凫、縮放等,還支持復(fù)雜的動(dòng)畫組合和定時(shí)器功能溢吻。
Core Graphics:CoreGraphics是一個(gè)2D圖形框架维费,可以用于創(chuàng)建和操作圖像和路徑。它提供了許多繪圖函數(shù)促王,可以用于繪制直線犀盟、矩形、橢圓蝇狼、圓弧等形狀阅畴,還支持顏色、漸變迅耘、圖案等特效贱枣。
Core Image:CoreImage是一個(gè)圖像處理框架,可以用于對(duì)圖像進(jìn)行濾鏡豹障、色彩調(diào)整冯事、變形等操作。它提供了多種濾鏡效果血公,可以輕松實(shí)現(xiàn)圖片的美化昵仅、修復(fù)等功能。
Core Video:CoreVideo是一個(gè)視頻處理框架,可以用于對(duì)視頻進(jìn)行解碼摔笤、編碼够滑、渲染等操作。它提供了多種視頻效果吕世,可以用于實(shí)現(xiàn)視頻編輯彰触、特效制作等功能。
這些框架通常被iOS開發(fā)者用來(lái)實(shí)現(xiàn)圖形圖像的渲染和顯示命辖,同時(shí)也可以用于創(chuàng)建各種精美的用戶界面和動(dòng)畫效果况毅。
這些框架仍然遵循圖形圖像渲染pipeline的基本架構(gòu),具體的技術(shù)棧如圖所示:
Core Animation (核心動(dòng)畫)
Core Animation
再說說Core Animation尔艇,如果你正在編寫iOS App尔许,那么無(wú)論你是否知道,你都在使用它终娃。Core Animation字面意思是“核心動(dòng)畫”味廊,但它本質(zhì)上可以理解為一個(gè)復(fù)合引擎,主要職責(zé)包含:渲染棠耕、構(gòu)建和實(shí)現(xiàn)動(dòng)畫余佛。
Core Animation最核心的功能是提供給上層框架“UIKit”和“AppKit”使用的Layer對(duì)象(iOS系統(tǒng)對(duì)應(yīng)的是CALayer),用來(lái)管理和控制屏幕上需要顯示的內(nèi)容(Content)窍荧,這些內(nèi)容被分解成獨(dú)立的Layer辉巡,存儲(chǔ)在一個(gè)叫做Layer Tree(圖層樹)的層級(jí)關(guān)系體系之中。于是這個(gè)Tree就形成了UIKit以及在iOS應(yīng)用程序當(dāng)中你所能在屏幕上看見的一切的基礎(chǔ)蕊退。
簡(jiǎn)單來(lái)說就是用戶能看到的屏幕上的內(nèi)容都由Layer對(duì)象進(jìn)行管理红氯。Layer對(duì)象中的Contents屬性保存了由設(shè)備渲染流水線渲染好的位圖Bitmap(通常也被稱為 backing store),而當(dāng)設(shè)備屏幕進(jìn)行刷新時(shí)咕痛,會(huì)從Layer對(duì)象中讀取生成好的Bitmap,進(jìn)而顯示到屏幕上喇嘱。
UIView 和 Layer
在iOS開發(fā)過程中茉贡,大量使用的視圖控件實(shí)際上是UIView而不是CALayer,UIView能夠呈現(xiàn)可視化內(nèi)容的原因是UIKit中的每一個(gè)UI視圖內(nèi)部都有一個(gè)關(guān)聯(lián)的CALayer者铜,用來(lái)呈現(xiàn)這些內(nèi)容腔丧。
從上面的層次結(jié)構(gòu)圖上來(lái)看,UIView處于比Core Animation更高的層級(jí)作烟,UIView除了利用Core Animation的CALayer提供可視內(nèi)容的繪制和動(dòng)畫(Drawing and Animation)能力外愉粤,還有其他兩個(gè)功能:
- 布局與子視圖的管理(Layout and subview management)。
- 事件處理(Event handling)拿撩。
Tree
在UIkit中所有的視圖都從一個(gè)叫做UIVIew的基類派生而來(lái)衣厘,視圖可以嵌套包含其他視圖-子視圖,子視圖也可以再嵌套包含其他子視圖,經(jīng)過數(shù)層的嵌套影暴,就形成一個(gè)由不同視圖組成的層級(jí)關(guān)系樹错邦,視圖樹(View Tree),如下圖所示型宙。
從上述描述我們知道撬呢,每一個(gè)UIView都有一個(gè)CALayer與之對(duì)應(yīng),我們把這個(gè)對(duì)應(yīng)的Layer叫做UIVIew的Backing Layer妆兑。在一個(gè)視圖樹中魂拦,每一個(gè)View的Layer也跟其View一樣組成層級(jí)關(guān)系樹,這個(gè)由Layer組成的樹叫做圖層樹(Layer Tree 或 Model Layer Tree)搁嗓。
View的職責(zé)之一就是創(chuàng)建管理這個(gè)與它對(duì)應(yīng)的Layer芯勘,以確保當(dāng)SubViews在視圖樹(View Tree)中添加或者被移除的時(shí)候,SubViews關(guān)聯(lián)的Layer也同樣在對(duì)應(yīng)的圖層樹(Layer Tree)中有著相同的操作谱姓。
那么為什么iOS要基于UIView和CALayer提供兩個(gè)平行的層級(jí)關(guān)系呢借尿,為什么要將 CALayer 獨(dú)立出來(lái),直接使用 UIView 統(tǒng)一管理不行嗎屉来?為什么不用一個(gè)統(tǒng)一的對(duì)象來(lái)處理所有事情呢路翻?
其實(shí)這樣設(shè)計(jì)的主要原因就是為了職責(zé)分離、功能拆分茄靠,方便代碼的復(fù)用茂契。iOS和MacOS下都可以使用Core Animation框架來(lái)負(fù)責(zé)可視內(nèi)容的渲染,但是兩個(gè)系統(tǒng)交互規(guī)則不同慨绳,所以要將渲染內(nèi)容和交互分開設(shè)計(jì)掉冶。所以iOS有UIKit和UIView,MacOS則是AppKit和NSView脐雪。
實(shí)際上并不是只有視圖樹(View Tree)和圖層樹(Layer Tree)這兩個(gè)層級(jí)關(guān)系樹厌小,還有呈現(xiàn)樹(Presentation Tree)、渲染樹(Render Tree)战秋,共四個(gè)璧亚,每一個(gè)Tree都扮演著不同的角色。
渲染樹(Render Tree):當(dāng)UIView對(duì)象需要渲染時(shí)脂信,它會(huì)將自己對(duì)應(yīng)的CALayer對(duì)象提交到渲染樹中癣蟋。在渲染樹中,CALayer對(duì)象會(huì)根據(jù)自己的層級(jí)關(guān)系和樣式信息進(jìn)行布局和繪制狰闪。渲染樹在Core Animation中還有一個(gè)重要的作用就是支持動(dòng)畫效果疯搅。當(dāng)View的某個(gè)屬性發(fā)生改變時(shí),Core Animation會(huì)自動(dòng)更新渲染樹中對(duì)應(yīng)CALayer對(duì)象的屬性埋泵,并使用硬件加速技術(shù)對(duì)視圖進(jìn)行動(dòng)畫渲染幔欧。
呈現(xiàn)樹(Presentation Tree)是渲染樹在動(dòng)畫過程中的一個(gè)快照,用于描述動(dòng)畫過程中每一幀Layer的狀態(tài)。當(dāng)對(duì)一個(gè)Layer進(jìn)行動(dòng)畫處理時(shí)琐馆,系統(tǒng)會(huì)根據(jù)動(dòng)畫開始和結(jié)束時(shí)的狀態(tài)规阀,生成一系列中間狀態(tài),這些狀態(tài)被稱為關(guān)鍵幀(Keyframe)瘦麸。每個(gè)關(guān)鍵幀都對(duì)應(yīng)著呈現(xiàn)樹中的一個(gè)狀態(tài)谁撼,當(dāng)動(dòng)畫播放時(shí),系統(tǒng)會(huì)根據(jù)關(guān)鍵幀逐漸改變Layer的狀態(tài)滋饲,從而實(shí)現(xiàn)流暢的動(dòng)畫效果厉碟。
呈現(xiàn)樹的實(shí)現(xiàn)原理非常簡(jiǎn)單,當(dāng)我們對(duì)一個(gè)Layer進(jìn)行動(dòng)畫處理時(shí)屠缭,系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)呈現(xiàn)樹箍鼓,用于保存Layer在動(dòng)畫過程中的狀態(tài)。每當(dāng)動(dòng)畫的狀態(tài)發(fā)生改變時(shí)呵曹,系統(tǒng)就會(huì)更新呈現(xiàn)樹中對(duì)應(yīng)CALayer對(duì)象的屬性款咖,從而反映出視圖的當(dāng)前狀態(tài)。呈現(xiàn)樹不會(huì)影響視圖(UIView)的布局和繪制過程奄喂,它僅僅用于保存Layer在動(dòng)畫過程中的狀態(tài)铐殃,所以它的計(jì)算成本非常小,可以實(shí)現(xiàn)高效的動(dòng)畫渲染跨新。
Core Animation(渲染管線)
Core Animation使用了一個(gè)基于GPU的渲染管線來(lái)呈現(xiàn)View和Layer富腊,并通過優(yōu)化和預(yù)合成來(lái)提高性能,我們把這個(gè)過程叫做Core Animation渲染管線域帐。
Core Animation渲染管線是從App開始赘被,App內(nèi)構(gòu)建了視圖層次結(jié)構(gòu),視圖層次結(jié)構(gòu)可以是View Tree肖揣,也可以是直接使用Core Animation構(gòu)建的的Layer Tree民假。
App不直接通過Core Animation做圖像的渲染工作,而是將上述的視圖層次結(jié)構(gòu)數(shù)據(jù)打包提交給Render Server(渲染服務(wù)器)龙优。Render Server是系統(tǒng)中一個(gè)獨(dú)立的進(jìn)程阳欲,App使用IPC(進(jìn)程間通信)的方式與Render Server進(jìn)行通信。Core Animation框架分為客戶端和服務(wù)器版本陋率,App內(nèi)使用的是Core Animation框架的客戶端版本,Render Server使用的是Core Animation服務(wù)器版本秽晚。
Render Server收到視圖層次結(jié)構(gòu)數(shù)據(jù)后瓦糟,Core Animation的服務(wù)端利用OpenGL/Metal渲染視圖層次結(jié)構(gòu)數(shù)據(jù),當(dāng)然渲染工作是在GPU中運(yùn)行的赴蝇。
視圖層次結(jié)構(gòu)數(shù)據(jù)渲染完成后菩浙,就可以通過顯示器(Display)將其顯示給用戶。
Render Loop (渲染循環(huán))
Render Loop(渲染循環(huán))是iOS系統(tǒng)中渲染圖形的核心循環(huán),Render Loop不間斷的捕獲用戶屏幕觸摸事件劲蜻,將事件傳遞給系統(tǒng)分析后陆淀,使用Core Animation渲染管線來(lái)更新相應(yīng)場(chǎng)景狀態(tài)和渲染顯示相應(yīng)圖形,確保應(yīng)用程序的圖形表現(xiàn)能夠?qū)崟r(shí)響應(yīng)用戶操作先嬉,并以流暢的方式呈現(xiàn)在屏幕上轧苫。
[圖片上傳失敗...(image-2c3b50-1684293991837)]
一個(gè)Core Animation渲染管線主要涉及以下幾個(gè)步驟:
Handle Events(事件處理):
應(yīng)用程序接收到iOS系統(tǒng)傳遞個(gè)它的事件(觸摸(Touch)、網(wǎng)絡(luò)回調(diào)(Networking)疫蔓、鍵盤操作(Keyboard)含懊、計(jì)時(shí)器(Timers)),應(yīng)用程序根據(jù)事件類型執(zhí)行對(duì)應(yīng)操作衅胀,比如創(chuàng)建和調(diào)整視圖層級(jí)岔乔、設(shè)置視圖的Frame、修改背景顏色滚躯、添加一個(gè)動(dòng)畫等雏门。
這些操作最終都會(huì)被CALayer標(biāo)記,并通過Core Animation提交到一個(gè)中間狀態(tài)中去掸掏。注意這時(shí)候?qū)σ晥D或者圖層屬性的修改還沒生效茁影,只是打上標(biāo)記,意思是需要更新阅束。開發(fā)者也可以使用setNeedsLayout來(lái)手動(dòng)標(biāo)記呼胚。
Commit Transaction (提交事務(wù)):
在Application的階段的最后一個(gè)一步是Commit Transaction,也是將呈現(xiàn)樹(Presentation Tree)打包發(fā)送給Render Server前的最后一步息裸。Commit Transcation其實(shí)可以細(xì)分為 4 個(gè)步驟:布局(Layout)蝇更、顯示(Display)、準(zhǔn)備(Prepare)呼盆、提交(Commit)年扩。
布局(Layout):
這個(gè)階段主要進(jìn)行視圖的構(gòu)建和布局,具體步驟包括
- 調(diào)用View里面重載的layoutSubviews方法访圃;
- 創(chuàng)建View厨幻,并通過addSubview方法添加SubView;
- 計(jì)算View的布局腿时,自動(dòng)布局約束的計(jì)算等况脆。
一旦計(jì)算出布局,系統(tǒng)就會(huì)調(diào)用setNeedsDisplay方法批糟,標(biāo)記View需要更新格了。
顯示(Display):
這個(gè)階段是交給Core Graphics的CGContext進(jìn)行視圖的繪制,并不是在顯示器上顯示徽鼎,主要繪制以下內(nèi)容:
- 如果開發(fā)者重寫了drawRect:方法盛末,那么系統(tǒng)會(huì)調(diào)用重載的drawRect:方法弹惦,在這個(gè)方法中繪制圖形,繪制的圖形bitmap數(shù)據(jù)保存在內(nèi)存中悄但。
- 使用Core Text或者Core Graphics進(jìn)行文字的繪制棠隐。
這個(gè)階段仍然使用CPU和系統(tǒng)內(nèi)存進(jìn)行繪制,還沒使用到顯卡檐嚣。
準(zhǔn)備(Prepare):
這階段Core Animation準(zhǔn)備將動(dòng)畫數(shù)據(jù)發(fā)送到渲染服務(wù)器助泽,一般進(jìn)行圖像的解碼和轉(zhuǎn)換等操作。
- 如果視圖或者子視圖里面包含圖像顯示净嘀,將會(huì)進(jìn)行圖像的解碼报咳;
- 如果視圖或者子視圖里面包含圖像顯示,但是這種圖像格式不被GPU不支持挖藏,那么執(zhí)行圖像轉(zhuǎn)換操作暑刃。
提交(Commit):
這階段將圖層進(jìn)行打包發(fā)送給Render Server。該過程會(huì)執(zhí)行遞歸圖層樹膜眠,所以如果圖層數(shù)太復(fù)雜岩臣,此階段產(chǎn)生更大的消耗。
以下階段就是在Render Server進(jìn)程中執(zhí)行了宵膨。
Decode(解碼):
當(dāng)上述打包好的圖層數(shù)據(jù)被傳輸?shù)絉ender Server之后架谎,首先會(huì)進(jìn)行Decode(解碼)操作。就是將打包的圖層數(shù)據(jù)解碼成Render Server能夠讀取的視圖層次結(jié)構(gòu)辟躏。完成解碼之后需要等待下一次垂直同步信號(hào)(VSync)后才會(huì)執(zhí)行下一步Draw Calls操作谷扣。 這個(gè)等待是為了保證上一個(gè)幀緩沖區(qū)的內(nèi)容能夠被完整的渲染顯示。
Draw Calls(繪制回調(diào)):
當(dāng)接收到下一次垂直同步信號(hào)(VSync)后捎琐,Render Server開始對(duì)GPU(在底層使用OpenGL 或Metal)發(fā)出繪制調(diào)用会涎。
Render(渲染)
當(dāng)收到Render Server繪制調(diào)用后,會(huì)立即開始渲染階段的操作瑞凑。渲染階段的操作可以分為兩個(gè)部分末秃,準(zhǔn)備(Render prepare)和執(zhí)行(Render execute)。
- 準(zhǔn)備渲染(Render prepare):準(zhǔn)備圖層樹籽御,準(zhǔn)備運(yùn)行GPU渲染管線的繪制命令练慕。根據(jù)事務(wù)提交階段的時(shí)間通過插值計(jì)算頁(yè)面上的動(dòng)畫當(dāng)前幀的狀態(tài);將圖層和特效分解為一步步簡(jiǎn)單操作技掏。
- 執(zhí)行渲染(Render execute):這階段使用GPU的渲染管線進(jìn)行一步步的圖形圖像繪制操作铃将,最終生成圖形以供下一步顯示。
理想的狀態(tài)是在收到下一個(gè)垂直同步信號(hào)(VSync)之前哑梳,就需要完成當(dāng)前所有的渲染操作劲阎,包括幀緩沖區(qū)的交換,因?yàn)槲覀兿M谑盏较乱粋€(gè)垂直同步信號(hào)(VSync)后能夠立即展示幀緩沖區(qū)中的渲染后的圖像涧衙。
Display(顯示)
此處的Display(顯示)和Commit Transaction階段的Display不一樣哪工,這個(gè)階段的Display就是顯示器從準(zhǔn)備好的幀緩沖區(qū)逐步取出像素信息展示在顯示器上。
以上各個(gè)階段的操作并不能在一個(gè)同步周期(兩個(gè)垂直同步信號(hào)之間的時(shí)間)內(nèi)一次性完成弧哎,蘋果為了優(yōu)化渲染管線流程雁比,提高圖形圖像的渲染效率,將上述各個(gè)階段的操作分散到多個(gè)同步周期中撤嫩,所以Render Loop(渲染循環(huán))中的多個(gè)渲染管線的時(shí)間是并行的交織在一起的偎捎。入下圖,當(dāng)CPU正在讀取第N幀時(shí)序攘,此時(shí)GPU正在渲染前一幀(第N-1幀)露戒,顯示器正在顯示N-2幀峭拘,如此交替往復(fù)就形成了Render Loop。
Offscreen Rendering(離屏渲染)
我們都知道,在屏幕中顯示內(nèi)容時(shí)删豺,通常需要使用至少一個(gè)幀緩沖區(qū)(Frame Buffer)來(lái)存儲(chǔ)像素?cái)?shù)據(jù),這是GPU用來(lái)渲染和存儲(chǔ)最終圖像的地方为朋。GPU會(huì)將渲染結(jié)果直接寫入幀緩沖區(qū)(Frame Buffer)疤孕,然后顯示在屏幕上。
然而距境,在某些情況下申尼,可能會(huì)有一些限制,使得不能或者不需要直接將渲染結(jié)果寫入幀緩沖區(qū)(Frame Buffer)垫桂。這些限制可能是由于特定的渲染效果师幕、開發(fā)者主動(dòng)指定的光柵化。在這種情況下诬滩,渲染結(jié)果需要先存儲(chǔ)到一個(gè)單獨(dú)的內(nèi)存區(qū)域--離屏緩沖區(qū)(Offscreen Buffer)霹粥,然后等到合適的時(shí)機(jī)再將其寫入幀緩沖區(qū)(Frame Buffer)。這個(gè)過程就被稱為離屏渲染(Offscreen Rendering)碱呼。
離屏渲染可以在不直接顯示在屏幕上的情況下進(jìn)行圖像處理和渲染操作蒙挑。通過將渲染結(jié)果存儲(chǔ)在離屏緩沖區(qū)中(Offscreen Buffer),可以進(jìn)行后續(xù)的處理愚臀、讀取或傳輸忆蚀。一些常見的用途包括圖像后處理、渲染到紋理(Render-to-texture)以及生成圖像數(shù)據(jù)供后續(xù)使用姑裂。
但是離屏渲染會(huì)增加渲染操作的延遲馋袜。一方面離屏渲染執(zhí)行過程中會(huì)使得GPU不斷在幀緩沖區(qū)(Frame Buffer)和離屏緩沖區(qū)(Offscreen Buffer)之間進(jìn)行上下文切換,這種切換的代價(jià)非常大舶斧;另一方面離屏渲染需要額外的內(nèi)存讀寫操作欣鳖,也需要更多的內(nèi)存來(lái)存儲(chǔ)渲染結(jié)果,所以大量的離屏渲染會(huì)內(nèi)存壓力過大茴厉。
離屏渲染的用途
離屏渲染可能帶性能問題泽台,那為什么還要使用離屏渲染技術(shù)呢什荣?
- 一些特殊渲染效果(比如Shadows、Masks, Rounded Rectangles怀酷、 Visual Effects等)需要使用離屏緩沖區(qū)來(lái)保存渲染的中間狀態(tài)稻爬,所以不得不使用離屏渲染。
- 為了效率蜕依,開發(fā)者可以將內(nèi)容提前渲染保存在離屏緩沖區(qū)中(開啟shouldRasterize光柵化)桅锄,后續(xù)如果使用直接從離屏緩沖區(qū)讀取即可,不需要重復(fù)渲染样眠。
Hitch(可能出現(xiàn)的性能問題)
通過上述的介紹友瘤,我們知道Render Loop的主要工作都是在CPU和GPU中進(jìn)行。CPU和GPU是并行進(jìn)行工作的檐束,當(dāng)CPU正在處理第N幀時(shí)辫秧,GPU正在渲染前一幀(第N-1),依此類推厢塘。所以茶没,CPU和GPU不能分別在一幀時(shí)間內(nèi)完成對(duì)應(yīng)的工作,都會(huì)延遲下一幀的處理晚碾、渲染和顯示抓半,用戶界面就會(huì)出現(xiàn)卡頓現(xiàn)象。
Commit hitch(提交故障)
在Commit Transaction(提交事務(wù))階段應(yīng)用程序可能需要花費(fèi)更多時(shí)間來(lái)處理事務(wù)格嘁,導(dǎo)致應(yīng)用程序不得不延遲向Render Server(渲染服務(wù)器)提交下一幀的圖層數(shù)據(jù)笛求,此階段發(fā)生的故障叫做Commit hitch(提交故障)。
發(fā)生Commit hitch主要是在Commit hitch這個(gè)階段主線程任務(wù)過重糕簿,可以通過以下方法減輕主線程的負(fù)擔(dān)探入。
盡可能的保持View輕量:
- 減少drawRect:方法的復(fù)雜度,如果CALayer的方法能夠替換自定義繪制的內(nèi)容盡量使用CALayer方法懂诗。
- 如果用不到drawRect:蜂嗽,就不要重寫drawRect:方法。
- 避免頻繁的創(chuàng)建和銷毀視圖殃恒,可以使用重用機(jī)制復(fù)用視圖植旧。
- 可以使用隱藏屬性替代頻繁的移除和插入視圖。
減少負(fù)擔(dān)重或者冗余的布局:
- 使用setNeedsLayout方法來(lái)刷新視圖布局而不是使用layoutIfNeeded方法离唐。
- 盡量減少約束的使用病附。
- 盡量減少遞歸布局的使用。
Render hitch(渲染故障)
上面提到Render階段有兩部分工作:渲染準(zhǔn)備和渲染執(zhí)行亥鬓。如果這兩部分的工作中的任一工作都沒有及時(shí)的在一幀的時(shí)間內(nèi)完成完沪,都會(huì)造成Render hitch(渲染故障)。
其中大量的離屏渲染工作是造成Render hitch的一個(gè)重要原因嵌戈,下面幾種情況會(huì)觸發(fā)離屏渲染:
- 使用了 mask 的 layer (layer.mask)
- 需要進(jìn)行裁剪的 layer (layer.masksToBounds / view.clipsToBounds)
- 設(shè)置了組透明度為 YES覆积,并且透明度不為 1 的 layer (layer.allowsGroupOpacity/layer.opacity)
- 添加了投影的 layer (layer.shadow*)
- 采用了光柵化的 layer (layer.shouldRasterize)
- 繪制了文字的 layer (UILabel, CATextLayer, Core Text 等)
所以如果開發(fā)者要避免發(fā)生Render hitch听皿,就要盡量避免觸發(fā)主動(dòng)或者被動(dòng)離屏渲染操作。
參考文檔:
1宽档、《iOS 頁(yè)面渲染 - 流程》
https://juejin.cn/post/7038170936163450910
2写穴、《iOS下的渲染框架》
https://zhuanlan.zhihu.com/p/157556221
3、《iOS Rendering 渲染全解析》
https://github.com/RickeyBoy/Rickey-iOS-Notes/blob/master/%E7%AC%94%E8%AE%B0/iOS%20Rendering.md
4雌贱、《Core Animation Basics》
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/CoreAnimationBasics/CoreAnimationBasics.html
5、《Understanding UIKit Rendering》
https://www.wwdcnotes.com/notes/wwdc11/121/
6偿短、《WWDC 2021: Avoid hitches and discover the Render Loop》
https://a11y-guidelines.orange.com/en/mobile/ios/wwdc/nota11y/2021/21hitches/
7欣孤、《Оптимизация рендера в iOS: frame buffer, Render Server, FPS, CPU vs GPU》
https://habr.com/ru/post/647177/
8、《Rendering performance of iOS apps》
https://dmytro-anokhin.medium.com/rendering-performance-of-ios-apps-4d09a9228930
9昔逗、《Advanced Graphics and Animations for iOS Apps》
https://www.wwdcnotes.com/notes/wwdc14/419/
10降传、《Core Animation Essentials》
https://www.wwdcnotes.com/notes/wwdc11/421/
11、《iOS Core Animation: The Layer Tree》
https://www.informit.com/articles/article.aspx?p=2128062