爲什麼iOS出現頁面卡頓?

1.爲什麼iOS出現頁面卡頓?
出現卡頓的現象,這是由於CPU計算和GPU渲染,之間未及時交換數據丟失幀導致的結果。 掉幀,也就是說CPU處理數據和GPU渲染時間過長導致掉幀 頁面顯示也就是卡頓

1、儘量用輕量級的對象,比如用不到事件處理的地方,可以考慮使用CALayer取代UIView

2、不要頻繁地調用UIView的相關屬性,比如frame、bounds、transform等屬性,儘量減少不必要的修改

3、儘量提前計算好佈局,在有需要時一次性調整對應的屬性,不要多次修改屬性

4、Autolayout會比直接設置frame消耗更多的CPU資源

5、圖片的size最好剛好跟UIImageView的size保持一致

6、控制一下線程的最大併發數量

7、儘量把耗時的操作放到子線程 文本處理(尺寸計算、繪製) 圖片處理(解碼、繪製)

1、儘量避免短時間內大量圖片的顯示,儘可能將多張圖片合成一張進行顯示

2、GPU能處理的最大紋理尺寸是4096x4096,一旦超過這個尺寸,就會佔用CPU資源進行處理,所以紋理儘量不要超過這個尺寸

3、儘量減少視圖數量和層次

4、減少透明的視圖(alpha<1),不透明的就設置opaque爲YES

5、儘量避免出現離屏渲染
在OpenGL中,GPU有2種渲染方式

On-Screen Rendering:當前屏幕渲染,在當前用於顯示的屏幕緩衝區進行渲染操作
Off-Screen Rendering:離屏渲染,在當前屏幕緩衝區以外新開闢一個緩衝區進行渲染操作

離屏渲染消耗性能的原因
需要創建新的緩衝區
離屏渲染的整個過程,需要多次切換上下文環境,先是從當前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結束以後,將離屏緩衝區的渲染結果顯示到屏幕上,又需要將上下文環境從離屏切換到當前屏幕

哪些操作會觸發離屏渲染?
光柵化,layer.shouldRasterize = YES

遮罩,layer.mask

圓角,同時設置layer.masksToBounds = YES、layer.cornerRadius大於0
考慮通過CoreGraphics繪製裁剪圓角,或者叫美工提供圓角圖片

陰影,layer.shadowXXX
如果設置了layer.shadowPath就不會產生離屏渲染

2.常見解決辦法

1).UIImageView儘量設置爲不透明 opque儘量設置爲YES 當UIImageView的opque設置爲YES的時候其alpha的屬性就會無效,UIImageView的半透明取決於其圖片半透明或者UIImageView本身的背景色合成的圖層view是半透明的。 如果圖片全部不是半透明就不會觸發圖層的blend操作,整個圖層就會不透明。 如果疊加的圖片有出現半透明的,就會立馬觸發圖層的blend操作,整個圖層不透明。 背景色儘可能設爲alpha值爲1 當某一塊圖層的alpha和其superView的背景色alpha不一樣的時候會觸發alpha合成操作,這是一項看似很簡單但卻是非常消耗CPU性能的操作。

2).UIView的背景色設置 UIView的背景色儘量不要設置爲clearColor,這樣也會觸發alpha疊加,在UITableView滑動的時候是非常消耗性能的。子視圖的背景色儘可能設置成其superView的背景色,這樣圖層合成的時候不會觸發blend操作。 最好不使用帶alpha通道的圖片,如果有alpha儘量讓UI設計人員取消alpha通道。

3).cell上layer儘量避免使用圓角 在工作中關於滑動界面我們會時常遇到cell行設置頭像爲圓角等需求,這時候我們儘量避免使用layder.cornerRadius,因爲這會觸發離屏渲染。離屏渲染很耗時間。 離屏渲染:是GPU渲染區的一個渲染緩衝區,我們所用的所有顯示屏的圖形圖像都是通過GPU進行渲染,然後顯示在屏幕上。GPU負責渲染會把渲染的圖形放到緩衝區然後CPU就會發一個垂直信號顯示到屏幕。 如果要使用圓角,我們可以設置爲layer.shouldRasterize = YES,其實這個設置是觸發光柵化,可以大大提高渲染的性能。我的理解光柵化就是類似於cell的重用機制。 光柵化:把第一次渲染好的圖層放到緩衝區,那麼下次不需要再離屏渲染直接就可以從緩衝區拿去使用。

4).優化圖片的加載方式 圖片的加載方式有兩種形式: UIImageView *image = [UIImageView imageView:@"1.png"]; UIImageView *image = [UIImageView imageWithContentOfFile:@"1.png"]; 兩種加載圖片方式的區別: 第一種:當我們經常需要這張圖片並且僅僅是小圖的時候,我們可以使用此種方式加載圖片。 這種方式是把圖片緩存在圖片緩存區,當我們使用的時候會通過圖片的名字也就是通過key的方式去查找圖片在緩存區的內存地址。 當我們使用很多圖片的時候系統就會開闢很多內存來存儲圖片,所以qq、微信我們很多時候都會去清除緩存操作。 第二種:當我們使用工程裏面的一張大圖並且使用次數很少甚至爲1次的時候,我們優先會採用這種方式加載圖片,這種方式當使用完圖片的時候會立即丟棄釋放資源,所以對性能不會帶來負擔。

5).儘量延遲圖片的加載 當我們在滑動頁面的時候尤其對於那種佈局特別複雜的cell,滑動的時候不要加載圖片,當滑動停止得時候再進行圖片的加載。 我們都知道不管是UITableView還是UIScrollView在滾動的時候需要顯示東西都是通過runLoop去拿。 當滾動的時候runLoop會處於NSRunLoopTrackingMode的模式,我們可以通過一個主線程隊列dispatch_after或者selfPerformSelector設置runLoop的模式爲NSDefaultRunLoopMode模式,就可以做到停止滾動再加載圖片。 注:其實嚴格意義上selfPerformSelector的事件就是在主線程隊列中等待。 優先加載理念 採用優先加載的理念,既先展示一部分,當滑動的時候再加載下面的一部分這樣就保持流暢。

6).避免阻塞主線程 讓圖片的繪製、圖片的下載、對象的創建、文本的渲染等這些耗時的操作儘可能採用子線程異步的方式去處理,對於layer及UI的操作不得不在主線程裏面,只能想辦法優化。

7).xib、storyBoard、純代碼的問題 蘋果推出storyboard確實爲開發者節省了大量的時間,提高了開發效率,但是對於那種 複雜的滑動界面,利用storyboard是非常消耗資源的,不信的可以試試用性能工具timeProfie看看CPU所佔的性能百分比,其CPU的資源遠遠大於純代碼佈局。

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