iOS性能優化

在性能優化中一個最具參考價值的屬性是FPS:Frames Per Second,其實就是屏幕刷新率,蘋果的iphone推薦的刷新率是60Hz,也就是說GPU每秒鐘刷新屏幕60次,這每刷新一次就是一幀frame,FPS也就是每秒鐘刷新多少幀畫面。靜止不變的頁面FPS值是0,這個值是沒有參考意義的,只有當頁面在執行動畫或者滑動的時候,FPS值才具有參考價值,FPS值的大小體現了頁面的流暢程度高低,當低于45的時候卡頓會比較明顯。

圖層混合:

每一個layer是一個紋理,所有的紋理都以某種方式堆疊在彼此的頂部。對于屏幕上的每一個像素,GPU需要算出怎么混合這些紋理來得到像素RGB的值。

當Sa = 0.5時,RGB值為(0.5, 0, 0),可以看出,當兩個不是完全不透明的CALayer覆蓋在一起時,GPU大量做這種復合操作,隨著這中操作的越多,GPU越忙碌,性能肯定會受到影響。

公式:

R = S + D * ( 1 – Sa )

結果的顏色是源色彩(頂端紋理)+目標顏色(低一層的紋理)*(1-源顏色的透明度)。

當Sa = 1時,R = S,GPU將不會做任何合成,而是簡單從這個層拷貝,不需要考慮它下方的任何東西(因為都被它遮擋住了),這節省了GPU相當大的工作量。

怎么檢測圖層混合:

1、模擬器debug- 選中 color blended layers紅色區域表示圖層發生了混合

2、Instrument-選中Core Animation-勾選Color Blended Layers

避免圖層混合:

1、確??丶膐paque屬性設置為true,確保backgroundColor和父視圖顏色一致且不透明

2、如無特殊需要,不要設置低于1的alpha值

3、確保UIImage沒有alpha通道

UILabel圖層混合解決方法:

iOS8以后設置背景色為非透明色并且設置label.layer.masksToBounds=YES讓label只會渲染她的實際size區域,就能解決UILabel的圖層混合問題

iOS8 之前只要設置背景色為非透明的就行

為什么設置了背景色但是在iOS8上仍然出現了圖層混合呢?

UILabel在iOS8前后的變化,在iOS8以前,UILabel使用的是CALayer作為底圖層,而在iOS8開始,UILabel的底圖層變成了_UILabelLayer,繪制文本也有所改變。在背景色的四周多了一圈透明的邊,而這一圈透明的邊明顯超出了圖層的矩形區域設置圖層的masksToBounds為YES時,圖層將會沿著Bounds進行裁剪 圖層混合問題解決了

iOS離屏渲染

怎么檢測離屏渲染:

1、模擬器debug-選中color Offscreen - Renderd離屏渲染的圖層高亮成黃 可能存在性能問題

2、真機Instrument-選中Core Animation-勾選Color Offscreen-Rendered Yellow

離屏渲染的觸發方式

設置了以下屬性時,都會觸發離屏繪制:

1、layer.shouldRasterize(光柵化)

光柵化概念:將圖轉化為一個個柵格組成的圖象。

光柵化特點:每個元素對應幀緩沖區中的一像素。

2、masks(遮罩)

3、shadows(陰影)

4、edge antialiasing(抗鋸齒)

5、group opacity(不透明)

6、復雜形狀設置圓角等

7、漸變

8、drawRect

例如我們日程經常打交道的TableViewCell,因為TableViewCell的重繪是很頻繁的(因為Cell的復用),如果Cell的內容不斷變化,則Cell需要不斷重繪,如果此時設置了cell.layer可光柵化。則會造成大量的離屏渲染,降低圖形性能。

如果將不在GPU的當前屏幕緩沖區中進行的渲染都稱為離屏渲染,那么就還有另一種特殊的“離屏渲染”方式:CPU渲染。如果我們重寫了drawRect方法,并且使用任何Core Graphics的技術進行了繪制操作,就涉及到了CPU渲染。整個渲染過程由CPU在App內同步地完成,渲染得到的bitmap最后再交由GPU用于顯示。

現在擺在我們面前得有三個選擇:當前屏幕渲染、離屏渲染、CPU渲染,該用哪個呢?這需要根據具體的使用場景來決定。

盡量使用當前屏幕渲染

鑒于離屏渲染、CPU渲染可能帶來的性能問題,一般情況下,我們要盡量使用當前屏幕渲染。

離屏渲染 VS CPU渲染

由于GPU的浮點運算能力比CPU強,CPU渲染的效率可能不如離屏渲染;但如果僅僅是實現一個簡單的效果,直接使用CPU渲染的效率又可能比離屏渲染好,畢竟離屏渲染要涉及到緩沖區創建和上下文切換等耗時操作

UIButton 的 masksToBounds = YES又設置setImage、setBackgroundImage、[button setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"btn_selected"]]];

下發生離屏渲染,但是[button setBackgroundColor:[UIColor redColor]];是不會出現離屏渲染的

關于 UIImageView,現在測試發現(現版本: iOS10),在性能的范圍之內,給UIImageView設置圓角是不會觸發離屏渲染的,但是同時給UIImageView設置背景色則肯定會觸發.觸發離屏渲染跟 png.jpg格式并無關聯

日常我們使用layer的兩個屬性,實現圓角

imageView.layer.cornerRaidus = CGFloat(10);

imageView.layer.masksToBounds = YES;

這樣處理的渲染機制是GPU在當前屏幕緩沖區外新開辟一個渲染緩沖區進行工作,也就是離屏渲染,這會給我們帶來額外的性能損耗。如果這樣的圓角操作達到一定數量,會觸發緩沖區的頻繁合并和上下文的的頻繁切換,性能的代價會宏觀地表現在用戶體驗上——掉幀

光柵化

光柵化是將幾何數據經過一系列變換后最終轉換為像素,從而呈現在顯示設備上的過程,光柵化的本質是坐標變換、幾何離散化

我們使用 UITableView 和 UICollectionView 時經常會遇到各個 Cell 的樣式是一樣的,這時候我們可以使用這個屬性提高性能:

cell.layer.shouldRasterize=YES;

cell.layer.rasterizationScale=[[UIScreenmainScreen]scale];

頁面間跳轉的性能優化:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 避免設置顏色透明度alpha 1秒默認刷60幀,每一幀顯示一張圖片 兩幀刷新之間運算沒有做完,就會卡 一定要用真機...
    geekAppke閱讀 170評論 0 0
  • 前言 工欲善其事,必先利其器。Instrument對于iOS開發來說,是發現并且解決問題的一把利器。 本文會用到的...
    iOS開發攻城獅閱讀 8,042評論 1 62
  • 總結一下平時優化app性能用到的方法 1.合理的分配線程,不要濫用多線程。開辟線程,以及線程之間的上下文切換是消耗...
    SpursGo閱讀 1,012評論 0 2
  • 1.啟動時間 應用啟動時間長短對用戶第一次體驗至關重要,同時系統對應用的啟動、恢復等狀態的運行時間也有嚴格的要求,...
    心至靜行至遠閱讀 1,505評論 2 4
  • 1.首先新建項目-打開protect-profile 左側 數值代表的fpsfps:我們知道任何屏幕總是有一個刷新...
    那位小姐閱讀 1,877評論 7 12