1. 程式人生 > >iOS如何提高頁面流暢度

iOS如何提高頁面流暢度

時間 oar should creat image splay https 性能 離屏渲染

A.提高CPU性能

對象創建
1.盡量用輕量的對象代替重量的對象,比如CALayer 比 UIView 要輕量許多,如果不考慮交互事件的話,可以選擇CALayer。
2.Storyboard和xib加載對象時,消耗的成本比代碼多。在使用時需要綜合考慮。
3.使用對象的預加載和懶加載,減少使用時加載的負擔。

對象調整
1.UIView 的關於顯示相關的屬性(比如 frame/bounds/transform)等實際上都是 CALayer 屬性映射來的,所以對 UIView 的這些屬性進行調整時,消耗的資源要遠大於一般的屬性。不用頻繁修改。
2.UIView和CALayer層次的修改會激發很多代理和通知,盡量少去調整層次。

對象的消耗
1.對象容器型對象的消耗需要重視,盡量放到後臺進行銷毀。
Tip:
NSArray *tmp = self.array;
self.array = nil;
dispatch_async(queue, ^{
[tmp class];
});

布局計算
1.app內視圖計算通常比較銷毀CPU性能,而且算出的結果通常是修改uiview的frame相關屬性,更是消耗cpu性能,所以盡量避免頻繁的布局更新

Autolayout
1.自動布局對cpu的消耗隨著復雜度是呈指數級的,故慎用

文本計算
1.頁面的文本計算一般是無法避免的,自己手動計算可以提高性能

文本渲染
1.常見的文本控件 (UILabel、UITextView 等),其排版和繪制都是在主線程進行的,當顯示大量文本時,CPU 的壓力會非常大。
對此解決方案只有一個,那就是自定義文本控件,用 TextKit 或最底層的 CoreText 對文本異步繪制。

圖片解碼
當用 UIImage 或 CGImageSource 的那幾個方法創建圖片時,生成的對象不會立即解碼,而是當圖片設置到 UIImageView 或者 CALayer.contents 中去,並且 CALayer 被提交到 GPU 前,CGImage 中的數據才會得到解碼。解碼都是在主線程中,影響性能。
常見的做法是在後臺線程先把圖片繪制到 CGBitmapContext 中,然後從 Bitmap 直接創建圖片。目前常見的網絡圖片庫都自帶這個功能。

圖像繪制
1.圖像的繪制通常是指用那些以 CG 開頭的方法把圖像繪制到畫布中,然後從畫布創建圖片並顯示這樣一個過程。這個最常見的地方就是 [UIView drawRect:] 裏面了。由於 CoreGraphic 方法通常都是線程安全的,所以圖像的繪制可以很容易的放到後臺線程進行。一個簡單異步繪制的過程大致如下(實際情況會比這個復雜得多,但原理基本一致):
- (void)display {
dispatch_async(backgroundQueue, ^{
CGContextRef ctx = CGBitmapContextCreate(...);
// draw in context...
CGImageRef img = CGBitmapContextCreateImage(ctx);
CFRelease(ctx);
dispatch_async(mainQueue, ^{
layer.contents = img;
});
});
}

B.提高GPU性能
紋理渲染
1.當在較短時間顯示大量圖片時(比如 TableView 存在非常多的圖片並且快速滑動時),CPU 占用率很低,GPU 占用非常高。避免這種情況的方法只能是盡量減少在短時間內大量圖片的顯示,盡可能將多張圖片合成為一張進行顯示。
2.當圖片過大,超過 GPU 的最大紋理尺寸時,圖片需要先由 CPU 進行預處理,這對 CPU 和 GPU 都會帶來額外的資源消耗。目前來說,iPhone 4S 以上機型,紋理尺寸上限都是 4096×4096。所以,盡量不要讓圖片和視圖的大小超過這個值。

視圖混合
1.當多個視圖或者CALayer混合顯示時,GPU會將它們混合到一起,如果視圖多,結構復雜就會增加混合難度。解決方法:減少視圖個數和層次,在不透明的視圖中標明opaque 屬性以避免無用的 Alpha 通道合成。或者把它們合成到一張大圖上。

圖形生成
1.CALayer 的 border、圓角、陰影、遮罩(mask),CASharpLayer 的矢量圖形顯示,通常會觸發離屏渲染(offscreen rendering),而離屏渲染通常發生在 GPU 中。當一個列表視圖中出現大量圓角的 CALayer,並且快速滑動時,可以觀察到 GPU 資源已經占滿,而 CPU 資源消耗很少。
為了避免這種情況,可以嘗試開啟 CALayer.shouldRasterize 屬性,但這會把原本離屏渲染的操作轉嫁到 CPU 上去。另外解決方法是把需要顯示的圖形在後臺線程繪制為圖片,避免使用圓角、陰影、遮罩等屬性。


異步渲染框架
AsyncDisplayKit,提高頁面的流暢度

參考文章:iOS 保持界面流暢的技巧 https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/

iOS如何提高頁面流暢度