iOS系統(tǒng)下的圖形圖像顯示原理

常用框架

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

再說說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),如下圖所示型宙。

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都扮演著不同的角色。

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渲染管線域帐。

pipeline

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)]

RenderLoop
RenderLoopOne

一個(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)畫等雏门。

Events

這些操作最終都會(huì)被CALayer標(biāo)記,并通過Core Animation提交到一個(gè)中間狀態(tài)中去掸掏。注意這時(shí)候?qū)σ晥D或者圖層屬性的修改還沒生效茁影,只是打上標(biāo)記,意思是需要更新阅束。開發(fā)者也可以使用setNeedsLayout來(lái)手動(dòng)標(biāo)記呼胚。

setNeesLayout

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)年扩。

LayoutAndDrawViews

布局(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。

TheRenderLoop

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)象。

gpu和cpu

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(提交故障)。

commithitch
commithitch

發(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(渲染故障)。

HitchesRenderPhaseHitch1

其中大量的離屏渲染工作是造成Render hitch的一個(gè)重要原因嵌戈,下面幾種情況會(huì)觸發(fā)離屏渲染:

  1. 使用了 mask 的 layer (layer.mask)
  2. 需要進(jìn)行裁剪的 layer (layer.masksToBounds / view.clipsToBounds)
  3. 設(shè)置了組透明度為 YES覆积,并且透明度不為 1 的 layer (layer.allowsGroupOpacity/layer.opacity)
  4. 添加了投影的 layer (layer.shadow*)
  5. 采用了光柵化的 layer (layer.shouldRasterize)
  6. 繪制了文字的 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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末勾怒,一起剝皮案震驚了整個(gè)濱河市婆排,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笔链,老刑警劉巖段只,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異鉴扫,居然都是意外死亡赞枕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門坪创,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)炕婶,“玉大人,你說我怎么就攤上這事莱预∧啵” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵依沮,是天一觀的道長(zhǎng)涯贞。 經(jīng)常有香客問我,道長(zhǎng)悉抵,這世上最難降的妖魔是什么肩狂? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮姥饰,結(jié)果婚禮上傻谁,老公的妹妹穿的比我還像新娘。我一直安慰自己列粪,他們只是感情好审磁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布谈飒。 她就那樣靜靜地躺著,像睡著了一般态蒂。 火紅的嫁衣襯著肌膚如雪杭措。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天钾恢,我揣著相機(jī)與錄音手素,去河邊找鬼。 笑死瘩蚪,一個(gè)胖子當(dāng)著我的面吹牛泉懦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疹瘦,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼崩哩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了言沐?” 一聲冷哼從身側(cè)響起邓嘹,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎险胰,沒想到半個(gè)月后汹押,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡起便,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年鲸阻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缨睡。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸟悴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奖年,到底是詐尸還是另有隱情细诸,我是刑警寧澤陋守,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響拿霉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一驮肉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)清笨。三九已至检号,卻和暖如春蛙酪,著一層夾襖步出監(jiān)牢的瞬間齐苛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工桂塞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凹蜂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓阁危,卻偏偏與公主長(zhǎng)得像玛痊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狂打,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 圖形渲染技術(shù)棧 下圖所示為 iOS App 的圖形渲染技術(shù)棧擂煞,App 使用 Core Graphics、Core ...
    KB_MORE閱讀 374評(píng)論 0 0
  • 首先回答一個(gè)問題:CPU和GPU都能進(jìn)行圖形渲染趴乡,只是GPU 圖形渲染的并行計(jì)算能力速度更快 屏幕圖像顯示原理 下...
    Fat_L閱讀 508評(píng)論 0 0
  • 原文鏈接 通過 圖形渲染原理 一文对省,大致能夠了解圖形渲染過程中硬件相關(guān)的原理。本文將進(jìn)一步介紹 iOS 開發(fā)過程中...
    baochuquan閱讀 5,993評(píng)論 1 38
  • 1. 圖形渲染框架 下圖為 iOS APP 圖形渲染框架, APP 在顯示可視化的圖形時(shí)惦辛,使用到了 Core A...
    小山93閱讀 1,154評(píng)論 0 0
  • 圖形渲染技術(shù)棧 下圖所示為 iOS App 的圖形渲染技術(shù)棧同仆,App 使用 Core Graphics、Core ...
    宋唐不送糖閱讀 602評(píng)論 0 2