原標題為:《Advanced Graphics and Animation For iOS Apps》。下載的文件名有點不同寸癌。本筆記內(nèi)容為視頻學(xué)習(xí)和實踐探索。另外 objc 的這篇文章《繪制像素到屏幕上》和本視頻的內(nèi)容有很大程度的交集,推薦一下汰扭。
視頻內(nèi)容
- Core Animation pipeline
- Rendering concepts
- UIBlurEffect
- UIVibrancyEffect
- Profiling tools
- Case studies
Core Animation Pipeline
這個章節(jié)的時長為06:35囤躁,但信息量非常大冀痕。每個小節(jié)拉出來都能另寫一章。
讓屏幕頁面流暢應(yīng)該保證頁面刷新率為 60 幀/秒狸演,1 幀的時間大概就是 16.67 ms了言蛇。Core Animation 這個框架的名字很具有誤導(dǎo)性,讓大家以為這個框架只是用來實現(xiàn)動畫的宵距,實際上 Core Animation 框架做了很多基礎(chǔ)工作:組合屏幕上的內(nèi)容腊尚,追蹤視圖結(jié)構(gòu)和內(nèi)容的變化。流程圖中 Commit Transaction 前面的紅框代表觸發(fā)視圖內(nèi)容變化的事件满哪,比如點擊按鈕婿斥,之后Core Animation 框架會捕獲到屏幕內(nèi)容的變化并提交給 Render Server(渲染服務(wù)器),Render Server 里另外一個版本的 Core Animation 框架負責(zé)解碼并繪制內(nèi)容哨鸭。
值得注意的是:在 Prepare 這個階段做的事是圖像解碼以及圖像轉(zhuǎn)換民宿。無論是網(wǎng)上下載的圖像還是從磁盤讀取圖像文件,得到的圖像一般是不能直接用于顯示的像鸡,需要解碼為位圖(bitmap)勘高。如果你的視圖中使用了 JPEGs 或是 PNGs的圖像,將在這個階段進行解碼;如果你使用了 GPU 不支持的圖像格式(就是 JPEG 和 PNG 之外的格式)华望,那么圖像就需要轉(zhuǎn)換格式蕊蝗。Path 團隊的圖像緩存開源庫FastImageCache就利用這個特性來加速圖像的顯示。
Rendering concepts
這一節(jié)介紹了一些基本的渲染知識:屏幕被分割成 NxN 像素的小塊來渲染赖舟,每個小塊的大小與 SoC(System on Chip) 的cache相關(guān)蓬戚。具體的操作過程如下:對于一個 app icon,被當做一個 CALayer 來渲染宾抓,而 CALayer 在 Core Animation 中被劃分為兩個三角形子漩,每個三角形可以被繼續(xù)分割成多個三角形,對每一個三角形單獨渲染石洗。
后面的幢泼,我看完之后基本就忘了,所以想了解到底怎么渲染的可以看看這一段讲衫。大致過程是渲染然后合成缕棵,在開頭的文章中有對這塊的敘述。
UIVisualEffectView
在 iOS 8 中蘋果放出了新的 UIView
子類 UIVisualEffectView
涉兽。蘋果在 iOS 7 中廣泛使用了虛化效果招驴,卻沒有給出接口,民間大多使用 GPUImage 這個庫來實現(xiàn)虛化效果枷畏,終于在 iOS 8 里給出了官方支持别厘。UIVisualEffectView
支持 UIBlurEffect 和 UIVibrancyEffect 兩種效果,前者是虛化內(nèi)容拥诡,后者在前者的基礎(chǔ)上再合成一個透明視圖触趴。
UIBlurEffect(虛化效果)的實現(xiàn)正是基于上一節(jié)提到的渲染+合成。其手法是這樣:抓取用作背景的內(nèi)容然后進行縮放以降低計算量渴肉,然后分別進行水平虛化和垂直虛化(翻譯得可能不對冗懦,就是橫著來一下,然后豎著來一下宾娜,而不是直接對整個內(nèi)容進行虛化批狐,降低計算量)扇售,最后將縮小的內(nèi)容再放大到原來的尺寸進行著色前塔。
效果有三種樣式:Extra light, Light, Dark。這三種樣式對性能的要求依次降低承冰。另外 iPad 2以及 iPad 3不支持虛化(who care?)华弓。而 UIVibrancyEffect 效果是在 UIBlurEffect 的基礎(chǔ)上再合成一個視圖。UIVibrancyEffect 效果對性能要求極高困乒,蘋果工程師建議避免對全屏使用該效果寂屏,并給出了優(yōu)化性能的建議:Rasterization 和 Group Opacity。
1.Rasterization
設(shè)置 CALayer 的 shouldRasterize 屬性為 YES 能夠為程序觸發(fā)離屏渲染(Offscreen Rendering),更新內(nèi)容時能夠額外渲染不在屏幕范圍上的內(nèi)容用作緩存迁霎;不要濫用吱抚,因為離屏渲染的緩存大小只有屏幕尺寸的 2.5 倍大;當離線渲染的內(nèi)容超過 100 ms 沒有使用將會被清除考廉。應(yīng)該在以下場景中才開啟該屬性:
- 繪制代價很大的靜態(tài)內(nèi)容
- 結(jié)構(gòu)非常復(fù)雜的視圖
要注意秘豹,離屏渲染的計算代價是很大的,與之相比昌粤,通過普通手段顯示內(nèi)容要廉價很多(有很多術(shù)語由于沒有鋪墊寫出來只會更讓人困惑既绕,還是推薦看開頭的文章)。只有當屏幕中的圖層不變時才可以利用這個選項來優(yōu)化涮坐。因此凄贩,在一般情況下,還是不要開啟離屏渲染的好袱讹。
2.Group Opacity
如果一個 layer 的 opacity 值小于 1.0 并且該 layer 含有子 layer 或者有背景圖像疲扎,開啟groupopacity 將會觸發(fā)離屏渲染。建議一直關(guān)閉該功能廓译,將 layer 的 allowsGroupOpacity 設(shè)置為 NO评肆。
Profiling Tool:
Xcode 套件中的 Instruments 工具估計是最沒有被有效利用的工具之一,我以前就只用來查看內(nèi)存占用以及泄露問題了非区。實際上利用 Instruments來對視圖和動畫性能調(diào)優(yōu)是非常高效的瓜挽。視圖和動畫的性能一旦有問題自然是非常不爽快的,相對于手工一遍遍主觀調(diào)試征绸,Instruments 能夠直接指出性能不佳的部分久橙,一目了然。
(Instruments 的文檔令人發(fā)指管怠,基本上找不到主講工程師在視頻中提到的 debug options)
主講的工程師在介紹工具之前給出了性能調(diào)優(yōu)的檢查選項:
Core Animation Instrument
在 Xcode 的菜單欄中依次選擇 Product->Profile 后淆衷,會啟動 Instruments 工具,有多種分析和調(diào)試工具渤弛,選擇 Core Animation祝拯。
根據(jù)視頻內(nèi)容探索了以下調(diào)試選項:
-
Color blended layers
屏幕上綠色的部分表示該處的 layer 是 opaque (不透明的),這樣 GPU 在合成時就不需要考慮該 layer 下面的內(nèi)容直接輸出該 layer 的內(nèi)容就夠了她肯;紅色的部分表示該處的內(nèi)容需要 blend(混合)佳头,GPU 需要將該 layer 以及該 layer 下方的內(nèi)容進行混合后才能輸出,工作量大晴氨。
IMG_0384.PNG - Color Hits Green and Misses Red
該選項與前面提到的Rasterization有關(guān)康嘉。綠色表明離屏渲染的 cache 中還有該部分的緩存,紅色表示該部分的緩存已被移除籽前。 - Color Copied Images
前面提到過亭珍,圖像要被解碼后才能用于顯示敷钾,GPU只支持對 JPEG 和 PNG 格式,其他格式的圖像需要由 CPU 來轉(zhuǎn)化解碼肄梨,最好放在后臺中解碼阻荒。
我在使用這個選項的時候未發(fā)現(xiàn)畫面有任何變化,嘗試了瀏覽 gif 也沒有發(fā)現(xiàn)異樣众羡〔扑桑看來需要使用這個選項的場景太少。 - Color MisalignedImages
找出對字節(jié)沒有對齊的圖像并進行著色纱控。當圖像尺寸與其容器 View 的尺寸不一樣的時候辆毡,需要把該圖像進行縮放。 - Color Offscreen-Renderd Yellow
將離屏渲染的部分標記為黃色甜害,查找出觸發(fā)離屏渲染的部分舶掖。 - Color Compositing Fast-Path Blue
將由顯示硬件(原話為 display hardware)進行混合的 layers 標記為藍色,這是個好事尔店,因為這意味著 GPU 的工作更少眨攘。 - Flash Updated Regions
標記屏幕上正在刷新的內(nèi)容為黃色。
看完這部分以后進行性能調(diào)優(yōu)不用到處猜瓶頸所在了嚣州,直接使用工具查看鲫售。
OpenGL ES Driver Instruments
在 Xcode 6.3 里,這個組件是找不到的该肴,應(yīng)該是改名成 GPU Driver 了情竹。這個組件可以用來統(tǒng)計大部分的運行參數(shù):CPU 占用,視圖幀率匀哄,渲染使用秦效,設(shè)備使用以及更多參數(shù)。我開發(fā)中的 App 的幀率還沒有超過 50 的涎嚼,真是慘不忍睹阱州。該組件可以回答性能優(yōu)化列表「Performance Investigation Mindset」中前面三個問題。
以前很少使用 Instruments,也因為我目前做的東西很少需要使用這些工具,當然還有可能是因為不知道能做什么所以沒法用埠忘,惡性循環(huán)。
View Debugging
Xcode 6 的新特性之一夜惭,可以在 Xcode 里實時查看 UI 結(jié)構(gòu)了,但只支持通過 Xcode 運行的 app刁憋。相比大名鼎鼎的 Reveal 還是有不少差距的滥嘴。
當然木蹬,兩者的定位不一樣至耻。目前來說對于調(diào)試夠用了若皱。
選擇調(diào)試工具
Case Study
案例學(xué)習(xí)這一塊給出了兩個常見的性能隱患:
1.陰影繪制
以前的常見代碼:
CALayer *imageViewLayer = cell.imageView.layer;
imageViewLayer.shadowColor = [UIColor blackColor].CGColor;
imageViewLayer.shadowOpacity = 1.0;
imageViewLayer.shadowRadius = 2.0;
imageViewLayer.shadowOffset = CGSizeMake(1.0, 1.0)
//設(shè)置了上面這些屬性后就能繪制陰影了,這樣一來Core Animation 必須知道陰影的形狀才能進行繪制尘颓,但這樣就必須使用離屏渲染來渲染內(nèi)容走触。(為啥,不明白)下面的方法可以避免離屏渲染疤苹。
imageViewLayer.shadowPath = CGPathCreateWithRect(imageRect, NULL)
2.圓角繪制
以往的常見代碼:
CALayer *imageViewLayer = cell.imageView.layer;
imageViewLayer.cornerRadius = imageHeight / 2.0;
imageViewLayer.masksToBounds = YES;
在給出的例子里互广,工程師使用一個 TableView 顯示一些圓形頭像。(由于說到關(guān)鍵時刻字幕消失了我聽不懂了卧土,所以不明白為什么這里產(chǎn)生了離屏渲染)我的理解是惫皱,由于重用機制,被重用的 Cell 每一次出現(xiàn)尤莺,Core Animation 都要為 Cell 繪制圓角旅敷,這種機制導(dǎo)致了離屏繪制。
工程師的建議是:
- 不要對重用的 Cell 使用 mask颤霎。
- 如果做不到上一點媳谁,嘗試這個方法來:
1.將 TableView 的背景設(shè)置為 solid white;
2.在縮略圖上方繪制一個圓形,圓形外圍為白色友酱;
這樣做減少了離屏渲染卻也增加了混合兩個圖層的工作晴音,但從性能上來說依然比原來好。
總結(jié):
離屏渲染代價昂貴缔杉,盡量避免
1·利用工具 CA Instrument 來找出它們
2·知道怎么做來避免它們(上面的 shadowPath 就是一個例子)(這個比較上锤躁,還沒搞清楚離屏渲染到底怎么觸發(fā)的)
在不同的設(shè)備上測試性能
1·使用 OpenGL ES Driver Instrument 來觀察 GPU
2·使用 Time Profiler Instrument 來觀察 CPU
知道視圖的結(jié)構(gòu)和任何隱含的繪制成本
1·這個對于 table cells 和滾動比較重要