開發蘋果手機 APP,如何保持iOS頁面流暢技巧

      iPhone上面的應用一直都是以流暢的操作體驗而著稱,但是由於之前開發人員把注意力更多的放在開發功能上面,比較少去考慮性能的問題,可能這其中涉及到objective-c,c++跟lua,優化起來相對複雜一些,導致應用在比如touch等較低端的產品上,光從啓動到進入頁面就花了將近一分鐘的時間,頁面之間的切換沒有那種很流暢的感覺,內存也居高不下,比較影響應用的用戶體驗。下面就常州開發APP公司來具體分析,iOS APP流暢問題優化技巧等:


產生卡頓的原因:


系統中 CPU、GPU、顯示器是以上面這種方式協同工作的。CPU 計算好顯示內容提交到 GPU,GPU 渲染完成後將渲染結果放入幀緩衝區,隨後視頻控制器會按照 VSync 信號逐行讀取幀緩衝區的數據,經過可能的數模轉換傳遞給顯示器顯示。

iOS 設備中的 CPU & GPU


CPU


加載資源,對象創建,對象調整,對象銷燬,佈局計算,Autolayout,文本計算,文本渲染,圖片的解碼, 圖像的繪製(Core Graphics)都是在CPU上面進行的。


GPU


GPU是一個專門爲圖形高併發計算而量身定做的處理單元,比CPU使用更少的電來完成工作並且GPU的浮點計算能力要超出CPU很多。


GPU的渲染性能要比CPU高效很多,同時對系統的負載和消耗也更低一些,所以在開發中,我們應該儘量讓CPU負責主線程的UI調動,把圖形顯示相關的工作交給GPU來處理,當涉及到光柵化等一些工作時,CPU也會參與進來,這點在後面再詳細描述。


相對於CPU來說,GPU能幹的事情比較單一:接收提交的紋理(Texture)和頂點描述(三角形),應用變換(transform)、混合(合成)並渲染,然後輸出到屏幕上。通常你所能看到的內容,主要也就是紋理(圖片)和形狀(三角模擬的矢量圖形)兩類。


CPU 和 GPU 的協作

由上圖可知,要在屏幕上顯示視圖,需要CPU和GPU一起協作,CPU計算好顯示的內容提交到GPU,GPU渲染完成後將結果放到幀緩存區,隨後視頻控制器會按照VSync信號逐行讀取幀緩衝區的數據,經過可能的數模轉換傳遞給顯示器顯示。


優化方案


在YY大神的 iOS 保持界面流暢的技巧中詳細介紹了 CPU 資源消耗原因和解決方案和 GPU 資源消耗原因和解決方案,這裏麪包括了開發中的大部分場景,可以幫助我們快速定位卡頓的原因,迅速解決卡頓。


下面是一些常見的優化方案!


TableViewCell 複用


在cellForRowAtIndexPath:回調的時候只創建實例,快速返回cell,不綁定數據。在willDisplayCell: forRowAtIndexPath:的時候綁定數據(賦值)。


高度緩存


在tableView滑動時,會不斷調用heightForRowAtIndexPath:,當cell高度需要自適應時,每次回調都要計算高度,會導致 UI 卡頓。爲了避免重複無意義的計算,需要緩存高度。


怎麼緩存?
  • 字典,NSCache。

  • UITableView-FDTemplateLayoutCell


視圖層級優化


不要動態創建視圖
  • 在內存可控的前提下,緩存subview。

  • 善用hidden。


減少視圖層級
  • 減少subviews個數,用layer繪製元素。

  • 少用clearColor,maskToBounds,陰影效果等。


減少多餘的繪製操作


圖片


  • 不要用JPEG的圖片,應當使用PNG圖片。

  • 子線程預解碼(Decode),主線程直接渲染。因爲當image沒有Decode,直接賦值給imageView會進行一個Decode操作。

  • 優化圖片大小,儘量不要動態縮放(contentMode)。

  • 儘可能將多張圖片合成爲一張進行顯示。


減少透明 view


使用透明view會引起blending,在iOS的圖形處理中,blending主要指的是混合像素顏色的計算。最直觀的例子就是,我們把兩個圖層疊加在一起,如果第一個圖層的透明的,則最終像素的顏色計算需要將第二個圖層也考慮進來。這一過程即爲Blending。

會導致blending的原因:

  • UIView的alpha<1。

  • UIImageView的image含有alpha channel(即使UIImageView的alpha是1,但只要image含有透明通道,則仍會導致blending)。


爲什麼blending會導致性能的損失?


原因是很直觀的,如果一個圖層是不透明的,則系統直接顯示該圖層的顏色即可。而如果圖層是透明的,則會引起更多的計算,因爲需要把另一個的圖層也包括進來,進行混合後的顏色計算。


  • opaque設置爲YES,減少性能消耗,因爲GPU將不會做任何合成,而是簡單從這個層拷貝。


減少離屏渲染


離屏渲染指的是在圖像在繪製到當前屏幕前,需要先進行一次渲染,之後才繪製到當前屏幕。


OpenGL中,GPU屏幕渲染有以下兩種方式:


  • On-Screen Rendering即當前屏幕渲染,指的是GPU的渲染操作是在當前用於顯示的屏幕緩衝區中進行。

  • Off-Screen Rendering即離屏渲染,指的是GPU在當前屏幕緩衝區以外新開闢一個緩衝區進行渲染操作。


爲什麼離屏渲染會發生卡頓?主要包括兩方面內容:


  • 創建新的緩衝區。

  • 上下文切換,離屏渲染的整個過程,需要多次切換上下文環境(CPU渲染和GPU切換),先是從當前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結束以後,將離屏緩衝區的渲染結果顯示到屏幕上又需要將上下文環境從離屏切換到當前屏幕。而上下文環境的切換是要付出很大代價的。


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


  • layer.shouldRasterize,光柵化

  • layer.mask,遮罩

  • layer.allowsGroupOpacity爲YES,layer.opacity的值小於1.0

  • layer.cornerRadius,並且設置layer.masksToBounds爲YES。可以使用剪切過的圖片,或者使用layer畫來解決。

  • layer.shadows,(表示相關的shadow開頭的屬性),使用shadowPath代替。

  • 兩種不同方式來繪製陰影: 不使用shadowPath


離屏渲染的優化建議


  • 使用ShadowPath指定layer陰影效果路徑。

  • 使用異步進行layer渲染(Facebook開源的異步繪製框架AsyncDisplayKit)。

  • 設置layer的opaque值爲YES,減少複雜圖層合成。

  • 儘量使用不包含透明(alpha)通道的圖片資源。

  • 儘量設置layer的大小值爲整形值。

  • 直接讓美工把圖片切成圓角進行顯示,這是效率最高的一種方案。

  • 很多情況下用戶上傳圖片進行顯示,可以在客戶端處理圓角。

  • 使用代碼手動生成圓角image設置到要顯示的View上,利用UIBezierPath(Core Graphics框架)畫出來圓角圖片。


合理使用光柵化 shouldRasterize


光柵化是把GPU的操作轉到CPU上,生成位圖緩存,直接讀取複用。


優點:
  • CALayer會被光柵化爲bitmap,shadows、cornerRadius等效果會被緩存。


缺點:
  • 更新已經光柵化的layer,會造成離屏渲染。

  • bitmap超過100ms沒有使用就會移除。

  • 受系統限制,緩存的大小爲 2.5X Screen Size。


shouldRasterize適合靜態頁面顯示,動態頁面會增加開銷。如果設置了shouldRasterize爲YES,那也要記住設置rasterizationScale爲contentsScale。


異步渲染


在子線程繪製,主線程渲染。例如 VVeboTableViewDemo


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章