IOS基礎知識-離屏渲染原理篇

優(yōu)化方案

官方對離屏渲染產(chǎn)生性能問題也進行了優(yōu)化:

iOS 9.0 之前UIimageView跟UIButton設置圓角都會觸發(fā)離屏渲染。

iOS 9.0 之后UIButton設置圓角會觸發(fā)離屏渲染,而UIImageView里png圖片設置圓角不會觸發(fā)離屏渲染了,如果設置其他陰影效果之類的還是會觸發(fā)離屏渲染的。

1、圓角優(yōu)化

在APP開發(fā)中,圓角圖片還是經(jīng)常出現(xiàn)的。如果一個界面中只有少量圓角圖片或許對性能沒有非常大的影響,但是當圓角圖片比較多的時候就會APP性能產(chǎn)生明顯的影響。

我們設置圓角一般通過如下方式:

imageView.layer.cornerRadius = CGFloat(10);

imageView.layer.masksToBounds = YES;

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

優(yōu)化方案1:使用貝塞爾曲線UIBezierPath和Core Graphics框架畫出一個圓角

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100,100,100,100)];

imageView.image = [UIImage imageNamed:@"myImg"];

//開始對imageView進行畫圖

UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,NO,1.0);

//使用貝塞爾曲線畫出一個圓形圖

[[UIBezierPath bezierPathWithRoundedRect:imageView.boundscornerRadius:imageView.frame.size.width]addClip];

[imageView drawRect:imageView.bounds];

imageView.image=UIGraphicsGetImageFromCurrentImageContext();

//結束畫圖

UIGraphicsEndImageContext();

[self.view addSubview:imageView];

優(yōu)化方案2:使用CAShapeLayer和UIBezierPath設置圓角

UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];

imageView.image = [UIImage imageNamed:@"myImg"];

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];

//設置大小

maskLayer.frame = imageView.bounds;

//設置圖形樣子

maskLayer.path = maskPath.CGPath;

imageView.layer.mask = maskLayer;

[self.view addSubview:imageView];

對于方案2需要解釋的是:

CAShapeLayer繼承于CALayer,可以使用CALayer的所有屬性值;

CAShapeLayer需要貝塞爾曲線配合使用才有意義(也就是說才有效果)

使用CAShapeLayer(屬于CoreAnimation)與貝塞爾曲線可以實現(xiàn)不在view的drawRect(繼承于CoreGraphics走的是CPU,消耗的性能較大)方法中畫出一些想要的圖形

CAShapeLayer動畫渲染直接提交到手機的GPU當中,相較于view的drawRect方法使用CPU渲染而言,其效率極高,能大大優(yōu)化內存使用情況。

總的來說就是用CAShapeLayer的內存消耗少,渲染速度快,建議使用優(yōu)化方案2。

2、shadow優(yōu)化

對于shadow,如果圖層是個簡單的幾何圖形或者圓角圖形,我們可以通過設置shadowPath來優(yōu)化性能,能大幅提高性能。示例如下:

imageView.layer.shadowColor=[UIColorgrayColor].CGColor;

imageView.layer.shadowOpacity=1.0;

imageView.layer.shadowRadius=2.0;

UIBezierPath *path=[UIBezierPathbezierPathWithRect:imageView.frame];

imageView.layer.shadowPath=path.CGPath;

我們還可以通過設置shouldRasterize屬性值為YES來強制開啟離屏渲染。其實就是光柵化(Rasterization)。既然離屏渲染這么不好,為什么我們還要強制開啟呢?當一個圖像混合了多個圖層,每次移動時,每一幀都要重新合成這些圖層,十分消耗性能。當我們開啟光柵化后,會在首次產(chǎn)生一個位圖緩存,當再次使用時候就會復用這個緩存。但是如果圖層發(fā)生改變的時候就會重新產(chǎn)生位圖緩存。所以這個功能一般不能用于UITableViewCell中,cell的復用反而降低了性能。最好用于圖層較多的靜態(tài)內容的圖形。而且產(chǎn)生的位圖緩存的大小是有限制的,一般是2.5個屏幕尺寸。在100ms之內不使用這個緩存,緩存也會被刪除。所以我們要根據(jù)使用場景而定。

3、其他的一些優(yōu)化建議

當我們需要圓角效果時,可以使用一張中間透明圖片蒙上去

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

使用異步進行l(wèi)ayer渲染(Facebook開源的異步繪制框架AsyncDisplayKit)

設置layer的opaque值為YES,減少復雜圖層合成

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

盡量設置layer的大小值為整形值

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

很多情況下用戶上傳圖片進行顯示,可以讓服務端處理圓角

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

Core Animation工具檢測離屏渲染

對于離屏渲染的檢測,蘋果為我們提供了一個測試工具Core Animation??梢栽赬code->Open Develeper Tools->Instruments中找到

image

Core Animation工具用來監(jiān)測Core Animation性能,提供可見的FPS值,并且提供幾個選項來測量渲染性能。如下圖:

image

下面我們來說明每個選項的功能:

Color Blended Layers:這個選項如果勾選,你能看到哪個layer是透明的,GPU正在做混合計算。顯示紅色的就是透明的,綠色就是不透明的。

Color Hits Green and Misses Red:如果勾選這個選項,且當我們代碼中有設置shouldRasterize為YES,那么紅色代表沒有復用離屏渲染的緩存,綠色則表示復用了緩存。我們當然希望能夠復用。

Color Copied Images:按照官方的說法,當圖片的顏色格式GPU不支持的時候,Core Animation會

拷貝一份數(shù)據(jù)讓CPU進行轉化。例如從網(wǎng)絡上下載了TIFF格式的圖片,則需要CPU進行轉化,這個區(qū)域會顯示成藍色。還有一種情況會觸發(fā)Core Animation的copy方法,就是字節(jié)不對齊的時候。如下圖:

image

Color Immediately:默認情況下Core Animation工具以每毫秒10次的頻率更新圖層調試顏色,如果勾選這個選項則移除10ms的延遲。對某些情況需要這樣,但是有可能影響正常幀數(shù)的測試。

Color Misaligned Images:勾選此項,如果圖片需要縮放則標記為黃色,如果沒有像素對齊則標記為紫色。像素對齊我們已經(jīng)在上面有所介紹。

Color Offscreen-Rendered Yellow:用來檢測離屏渲染的,如果顯示黃色,表示有離屏渲染。當然還要結合Color Hits Green and Misses Red來看,是否復用了緩存。

Color OpenGL Fast Path Blue:這個選項對那些使用OpenGL的圖層才有用,像是GLKView或者 CAEAGLLayer,如果不顯示藍色則表示使用了CPU渲染,繪制在了屏幕外,顯示藍色表示正常。

Flash Updated Regions:當對圖層重繪的時候回顯示黃色,如果頻繁發(fā)生則會影響性能??梢杂迷黾泳彺鎭碓鰪娦阅?。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1 CALayer IOS SDK詳解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi閱讀 5,331評論 3 23
  • 屏幕顯示圖像的原理: 高中物理應該學過顯示器是如何顯示圖像的:需要顯示的圖像經(jīng)過CRT電子槍以極快的速度一行一行的...
    青火閱讀 27,858評論 18 104
  • 屏幕渲染的原理: 需要顯示的圖像經(jīng)過CRT電子槍以極快的速度一行一行的掃描,掃描出來就呈現(xiàn)了一幀畫面,隨后電子槍又...
    一條魚的星辰大海閱讀 604評論 1 4
  • 一、概述 OpenGL ES是一套多功能開放標準的用于嵌入系統(tǒng)的C-based的圖形庫,用于2D和3D數(shù)據(jù)的可視化...
    半島夏天閱讀 354評論 0 2
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,621評論 1 32

友情鏈接更多精彩內容