iOS 性能優化思路:界面離屏渲染、圖層混色

手機性能優化的重點,就是界面渲染。通常,計算任務都交給服務端。html

界面渲染慢,就很差了。git


常見問題,就是離屏渲染。 這裏用 NSShadow 處理掉 CALayer 的陰影屬性帶來的離屏渲染。

常見的離屏渲染代碼: 繪製陰影,github

var label = UILabel()
        label.layer.shadowColor = UIColor.lightGray.cgColor
        label.layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
        label.layer.shadowOpacity = 1.0
        label.layer.shadowRadius = 5.0
        label.text = "離屏渲染"
複製代碼

寫完之後,CPU 和 GPU 都沒有充足的信息繪製陰影效果。api

過程是, CPU 會先把文本傳出去,請求 GPU (CPU 把文本傳給 GPU ),建立一個內存中的位圖上下文(GPU 把文本放進去 ),離屏渲染這就開始了。緩存

這個上下文缺信息,不在屏幕上, 不是幀緩衝。(渲染出來的圖形上下文,不屬於當前幀)。性能優化

image

以前 CPU 把文本處理好了,如今 CPU 處理文本效果(這裏是陰影)。

而後,CPU 拿到渲染好的文字,基於渲染出來的每個像素的透明度,計算出陰影的形狀。bash

最後,CPU 把最新計算出來的文字陰影形狀的信息,傳給 GPU . GPU 有陰影信息,有以前圖形上下文的渲染文本,GPU 就渲染好了最終的文字及其陰影,交給幀緩衝 (Frame Buffer), 咱們就看到了。app

這段代碼要渲染兩次,出現了離屏渲染。對 GPU 的性能有影響。他須要等待 CPU 來算出陰影的形狀。框架

由於咱們要 60 的幀數 ( FPS ), GPU 準備幀緩衝,渲染出當前幀,只有 17 毫秒的時間。拖累了主線程,屏幕刷新不過來。ide


對於圖形陰影, 用 layer 的 shadowPath. 對於文字陰影,用 NSShadow .

layer 的四個屬性 shadowColor , shadowOffset ,shadowOpacity ,shadowRadius ,通常性能很差。

對於一個視圖框, 經過 layer 在周邊加陰影。用 layer 的 shadowPath,建立一個 UIBezierPath,

UIBezierPath(rect: CGRect(x: 0, y: 0, width: 50, height: 50))
// size of your label
複製代碼

與以前不一樣,圖層不用渲染兩次。如今 GPU 有了足夠的信息繪製陰影效果, 就不用離屏渲染了。

對於文字陰影,用 NSShadow ,用 layer.path 就比較難。


UI 性能優化主要用的是 Instruments 的 Core Animation 模版。

過去,Core Animation 模版幾個調試選項很是強大,正常的綠色, 異常的紅色,離屏渲染的黃色。

(光柵化有效,光柵化後緩存的內容成功複用。界面會顯示綠色。

光柵化失效的部分,呈紅色。光柵化後緩存的內容沒有複用,光柵化隱式建立的位圖浪費了。直接從新繪製。 )

如今這些利器都在 Xcode 裏了,能夠直接使用。

真機運行直接選擇,

直接 debug

本文 Demo 使用的是 500 px 的 API .

調試界面的離屏渲染,用的是 Color Offscreen-Rendered Yellow 選項。

調試目標是,出現大片的綠色。

離屏渲染

這裏能夠用 Apple 的 UIKit 框架下的 NSShadow 對象。

let shadow = NSShadow()
            shadow.shadowColor = UIColor.lightGray
            shadow.shadowOffset = CGSize(width: 0.0, height: 5.0)
            shadow.shadowBlurRadius = 5.0
            if let mutableAttributedString = label.attributedText as? NSMutableAttributedString{
                let range = NSRange(location: 0, length: mutableAttributedString.string.count)
                mutableAttributedString.addAttribute(NSAttributedString.Key.shadow, value: shadow, range: range)
            }

複製代碼

解決離屏渲染

用背景色處理掉混色。

界面圖層混色,就是多個視圖的位置有重疊,他們又不是透明的。重疊區域的每個像素,GPU 須要算出一種新的顏色(混色)。 若是這種效果,不是 UI 設計的,儘可能避免。

調試界面的圖層混色,用的是 Color Blended Layer 選項。

UILabel 建議設置背景色。UILabel 有文字,那就不透明,Label 默認的背景色是透明色,與父視圖的背景色,混雜了。GPU 對相關位置的顏色,須要從新計算。

指定 Lable 背景色前

override func awakeFromNib() {
        super.awakeFromNib()
        [userNameLabel, photosLikeLabel, photosDescriptionLabel, photoTimeIntevalSincePostLabel].forEach {
            $0?.backgroundColor = UIColor.white
        }
}

複製代碼

設置後, 效果明顯

指定 Lable 背景色後

混色,若是不是 UI 指定的效果,建議處理掉。

界面圖層混色,常見的影響因素是 view 的 alpha 屬性。 alpha 小於 1, 通常自帶混色效果。

相關代碼: github.com/BoxDengJZ/I…

其餘知識點介紹: 卡頓(丟幀)。

Instruments 的 Core Animation 模版的時間線,就是 FPS. 顯示隨着時間,App 的幀率波動。

Instruments 的 Core Animation

能夠方便的讀取幀數,直觀的瞭解那些界面要改善。

用代碼檢測卡頓,天然是 CADisplayLink ,網上相關博客不少。

相關資源:

視頻教程,practical-instruments

Apple, Performance Tips

相關文章
相關標籤/搜索