iOS繪制和渲染

前言

我們平常iOS開發(fā)中,很少有機(jī)會能夠深入的了解繪制和渲染詳細(xì)的底層過程,在UI顯示方面,我們大多時(shí)候都只知其然而不知其所以然,然后在遇到一些UI方面的性能問題,內(nèi)存問題,這部分知識就尤其重要了,我們今天就來探究一下iOS繪制渲染的整個(gè)過程。

相關(guān)框架

框架結(jié)構(gòu)

這張截圖是蘋果官方文檔中,關(guān)于視覺相關(guān)的一個(gè)框架結(jié)構(gòu)圖。

  • UIKit

我們可以看到,最上層的框架就是我們平時(shí)開發(fā)最常用到的UIKit(Mac開發(fā)是AppKit)UIkit為我們封裝了大量的視圖,窗口,視圖結(jié)構(gòu)等豐富的UI元素,以及事件處理結(jié)構(gòu),文本圖像支持等等,我們可以直接使用UIKit來完成我們平時(shí)開發(fā)中絕大多數(shù)視圖的相關(guān)實(shí)現(xiàn),非常簡單方便。

  • CoreAnimation(QuartzCore)

在接下來的底層基礎(chǔ)設(shè)施中,最上層的框架為CoreAnimation,提到CoreAnimation,我們可能會想到它是動畫相關(guān)功能的庫,這其實(shí)是對它非常大的一個(gè)誤解,實(shí)際上,動畫功能只是CoreAnimation的一部分,它的原名叫做LayerKit,這樣一說,你就能知道,它正真的核心是什么了吧,CoreAnimation組合了不同的可視視圖,形成一個(gè)個(gè)獨(dú)立的圖層,存儲在圖層樹中,而UIKit的UIView視覺顯示上完全依賴這個(gè)圖層,UIView封裝了CALayer并添加了一些CALayer并不具備的功能,例如交互事件等。

  • CoreGraphics

CoreGraphics是底層繪圖框架,我們平時(shí)可以直接調(diào)用它的API做一些自定義視圖,它使用了Quartz2D引擎,calyer是CoreGraphics封裝出來的圖層類,calayer知道如何利用CoreGraphics繪制自己。

  • Metal

Metal是蘋果最新推出的底層渲染編程接口,是針對iphone和ipad中的GPU高度優(yōu)化的編程框架,是iOS平臺中最接近底層硬件的圖形框架。

視圖和動畫渲染過程

渲染過程我們可以分成6個(gè)階段:

APP內(nèi)部4個(gè)階段:

1. 布局:為圖層準(zhǔn)備層級關(guān)系,位置,顏色等等。

2. 創(chuàng)建BackingStore Image(寄宿圖片): 這個(gè)階段如果需要的話,創(chuàng)建layer的backing image,可能是通過layer的Contents傳入的,也可能是drawRect、drawLayer:inContext:方法畫出來的。

3. 準(zhǔn)備以及解壓:這個(gè)階段,Core Animation框架準(zhǔn)備各種渲染需要的數(shù)據(jù),解壓需要顯示的圖片。

4. 提交:這個(gè)階段Core Animation打包layer的所有信息,以及動畫參數(shù),通過IPC(進(jìn)程內(nèi)通訊)傳遞給Render Server。(此步驟遞歸,如果layerTree比較復(fù)雜,則開銷較大)。

APP外部2個(gè)階段:

到達(dá)render Server后會轉(zhuǎn)化為render Tree,進(jìn)行下面的步驟:

5. 渲染前準(zhǔn)備和計(jì)算:所有l(wèi)ayer的屬性,如果是動畫,計(jì)算中間值,準(zhǔn)備渲染。

6. 渲染:渲染到屏幕上。

這6個(gè)階段中,前5個(gè)都是由CPU處理的,最后一個(gè)階段才由GPU處理;我們能控制的只有前面兩個(gè)階段,剩下的工作由系統(tǒng)框架幫我們處理;如果是動畫,最后兩個(gè)步驟會一直重復(fù),知道動畫結(jié)束。

我們知道iOS設(shè)備的屏幕刷新率是60fps,如果沒有在1/60s內(nèi)結(jié)束這6個(gè)步驟就會掉幀視覺感受就是在卡。如下圖:

掉幀原理

所以,我們在動畫性能調(diào)優(yōu)方面的策略就是讓CPU和GPU都可以在這1/60秒內(nèi)做完他們應(yīng)該做的事情,如果有卡頓,我們便要找出來是CPU負(fù)擔(dān)太重,還是GPU負(fù)擔(dān)太重,找到原因后相應(yīng)的給他們減負(fù)。

繪制渲染相關(guān)優(yōu)化

耗費(fèi)CPU的性能的項(xiàng)目

  • 布局計(jì)算:當(dāng)視圖層級復(fù)雜,frame變化,需要復(fù)雜計(jì)算,會加重CPU的計(jì)算負(fù)擔(dān)。例如:動態(tài)計(jì)算tableviewCell的高度,使用autolayout也會非常耗費(fèi)計(jì)算CPU的性能。
  • 圖片的解壓和轉(zhuǎn)換:渲染前會解壓壓縮的圖片,而且如果圖片顏色格式不是32位的,那么CPU會進(jìn)行顏色格式轉(zhuǎn)換,所以,我們最好直接提供32位顏色格式的圖片。
  • 繪制需求:直接使用CaLayer進(jìn)行繪制的話,當(dāng)我們重寫UIView的drawRect方法,或者是drawLayer方法,那么系統(tǒng)會創(chuàng)建layer的寄宿圖,這種方式繪制會使得內(nèi)存暴增。盡量避免,建議使用CAShapeLayer進(jìn)行繪制,CAShapeLayer使用了硬件加速,渲染速度更快,內(nèi)存使用非常穩(wěn)定,不會被圖層邊界切割,也不會像素化。
  • 隱藏的繪制:UILable的文字都是畫到寄宿圖片上的,如果改變frame,會重新繪制。
  • 多層級視圖:如果一個(gè)layer被另一個(gè)layer完全遮蓋,GPU不會渲染被遮蓋的視圖,但是計(jì)算是否完全被遮蓋,很消耗CPU資源

耗費(fèi)GPU的性能的項(xiàng)目

  • 圖層混合overdraw:一個(gè)像素點(diǎn)被多次使用顏色填充,如果太多的話,肯定會影響GPU性能。如果一個(gè)視圖是不透明的我們應(yīng)該設(shè)置opaque為yes,主動告訴GPU。
  • 離屏渲染Off-Screen Rendering:某些屬性的設(shè)置,會出發(fā)離屏渲染,而離屏渲染會讓GPU在當(dāng)前屏幕緩沖區(qū)以外再開拓一個(gè)新的緩沖區(qū),進(jìn)行渲染操作,創(chuàng)建完新的緩沖區(qū)會進(jìn)行上下文切換,切到新緩沖區(qū),渲染完再切回來,把新緩沖區(qū)的結(jié)果帶回來顯示,這一切操作,都比較耗費(fèi)GPU的資源。

關(guān)于優(yōu)化的問題,我們?nèi)蘸笤僭敿?xì)分析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容