總結(jié)
避免圖層混合
- 確保控件的opaque屬性設(shè)置為true,確保backgroundColor和父視圖顏色一致且不透明
- 如無(wú)特殊需要,不要設(shè)置低于1的alpha值
- 確保UIImage沒(méi)有alpha通道
避免臨時(shí)轉(zhuǎn)換
- 確保圖片大小和frame一致,不要在滑動(dòng)時(shí)縮放圖片
- 確保圖片顏色格式被GPU支持,避免勞煩CPU轉(zhuǎn)換
慎用離屏渲染
- 絕大多數(shù)時(shí)候離屏渲染會(huì)影響性能
- 重寫(xiě)drawRect方法,設(shè)置圓角、陰影、模糊效果,光柵化都會(huì)導(dǎo)致離屏渲染
- 設(shè)置陰影效果是加上陰影路徑
- 滑動(dòng)時(shí)若需要圓角效果,開(kāi)啟光柵化
- 為什么要把控件盡量設(shè)置成不透明的,如果是透明的會(huì)有什么影響,如何檢測(cè)這種影響?
注解:
很多文章里說(shuō)把控件設(shè)置為opaque = true,其原理就是希望避免圖層混合,然而這種調(diào)優(yōu)一般情況下用處不大。因?yàn)閁IView的opaque屬性默認(rèn)值就是true,也就是說(shuō)只要不是人為設(shè)置成透明,都不會(huì)出現(xiàn)圖層混合。
個(gè)人認(rèn)為比opaque屬性更重要的是backgroundColor屬性,如果不設(shè)置這個(gè)屬性,控件依然被認(rèn)為是透明的,所以我們做的第一個(gè)優(yōu)化是在CustomTableCell類(lèi)的init方法中添加一行代碼:
label.backgroundColor = UIColor.whiteColor()
- 為什么cell中的圖片,盡可能要使用正確的大小、格式,如果錯(cuò)誤會(huì)有什么影響,如何檢測(cè)這種影響?
- 為什么設(shè)置陰影和圓角有可能影響滑動(dòng)時(shí)流暢度?
- shouldRasterize和離屏渲染的關(guān)系是什么,何時(shí)應(yīng)該使用?
光柵化
光柵化是將一個(gè)layer預(yù)先渲染成位圖(bitmap),然后加入緩存中。如果對(duì)于陰影效果這樣比較消耗資源的靜態(tài)內(nèi)容進(jìn)行緩存,可以得到一定幅度的性能提升。demo中的這一行代碼表示將label的layer光柵化:
label.layer.shouldRasterize = true
顏色格式
圖片大小
在demo中,每個(gè)UIImageView的大小都是180x180,而只有第二張圖片的像素大小是360x360。因此除了第二張圖片,其他的圖片都需要被縮放。
圖片的縮放需要占用時(shí)間,因此我們要盡可能保證無(wú)論是本地圖片還是從網(wǎng)絡(luò)或取得圖片的大小,都與其frame保持一致
第三個(gè)優(yōu)化是調(diào)整所有圖片的像素大小以避免不必要的縮放。
離屏渲染
離屏渲染可能會(huì)自動(dòng)觸發(fā),也可以手動(dòng)觸發(fā)。以下情況可能會(huì)導(dǎo)致觸發(fā)離屏渲染:
- 重寫(xiě)drawRect方法
- 有mask或者是陰影(layer.masksToBounds, layer.shadow*),模糊效果也是一種mask
- layer.shouldRasterize = true
前兩者會(huì)自動(dòng)觸發(fā)離屏渲染,第三種方法是手動(dòng)開(kāi)啟離屏渲染。
使用了陰影,接下來(lái)我們進(jìn)行第四個(gè)優(yōu)化,在設(shè)置陰影效果的四行代碼下面添加一行:
imgView.layer.shadowPath = UIBezierPath(rect:imgView.bounds).CGPath
這行代碼制定了陰影路徑,如果沒(méi)有手動(dòng)指定,Core Animation會(huì)去自動(dòng)計(jì)算,這就會(huì)觸發(fā)離屏渲染。
如果人為指定了陰影路徑,就可以免去計(jì)算,從而避免產(chǎn)生離屏渲染。
設(shè)置cornerRadius本身并不會(huì)導(dǎo)致離屏渲染,但很多時(shí)候它還需要配合layer.masksToBounds = true使用。
根據(jù)之前的總結(jié),設(shè)置masksToBounds會(huì)導(dǎo)致離屏渲染。
解決方案是盡可能在滑動(dòng)時(shí)避免設(shè)置圓角,如果必須設(shè)置圓角,可以使用光柵化技術(shù)將圓角緩存起來(lái):
// 設(shè)置圓角
label.layer.masksToBounds = true
label.layer.cornerRadius = 8
label.layer.shouldRasterize = true
label.layer.rasterizationScale = layer.contentsScale
轉(zhuǎn)載:https://bestswifter.com/uikitxing-neng-diao-you-shi-zhan-jiang-jie/