UIImageView UIView圓角與效能之間的研究與優化
設想:
找出直接設定圓角(maskToBounds/clipsToBounds)幀數下降的例子,
然後利用Runtime的Method Swizzle交換系統的setClipsToBounds方法
若設定了layer.cornerRadius 且 clipsToBounds = YES, 則clipsToBounds不會設定為YES,
而是通過各種其他方法設定圓角, 例如:
1.生成一個圓形的CALayer作為UIImageView.layer.mask.
2.非同步剪裁圖片.
(以上方法均為網路上流傳效能優化方法)
複製程式碼
場景:
在日曆中每一個UICollectionCell增加一個UIImageView並設定圓角
複製程式碼
實際:
圖為直接設定cornerRadius和maskToBounds屬性, 在如此多的圓角圖片下,依然是60幀.
手機iPhone6, 系統為iOS10, 網上傳的比較多的是iOS9以上png圖片不會觸發離屏渲染,
所以不會怎麼影響效能, 但我換成jpg圖片 依然是60幀.
但我還是嘗試了一下上面的兩種方法, 看是什麼作用:
1.生成一個圓形的CALayer作為UIImageView.layer.mask:
幀數明顯降低.
2.非同步剪裁圖片.
正常操作幀數沒有異常, 快速滑動, 會在cell的重用上出問題, 幀數明顯下降.
以上肉眼觀察明顯, 並不需要instrument監控.
所以圖片真的沒必要非同步剪裁!
所以圖片真的沒必要非同步剪裁!
所以圖片真的沒必要非同步剪裁!
複製程式碼
UIImageView 結論
在百分之九十九的情況下,
放心使用系統自己的maskToBounds/clipsToBounds與cornerRadius吧,
不會有任何效能問題,
實際上圓角對於安卓都不是事,
iOS缺老生常談,確實不應該啊.(基於專案不相容iOS8了)
UIImageView確定了結果,
但實際上圓角的設定遠不是UIImageView,
怎麼對UIView設定圓角並且保持較好的效能,
網上爬文也難有一個比較結論性的回答.
再測試一下直接對UIView直接設定圓角.
複製程式碼
場景:
依然是日曆, 每一個cell中有2個UILabel.
複製程式碼
實際:
這次就出問題了, 滑動幀數直接降到15左右
複製程式碼
依然按照上面的思路進行優化, 交換方法為setClipsToBounds與layoutSubViews,
在設定clipsToBounds = YES且layer.cornerRaius > 0的情況下,
layoutSubViews中進行優化:
1.生成一個圓形的CALayer作為UIImageView.layer.mask:
幀數明顯更低了, 所以這種方法在網上流傳簡直是害人...平均幀數不及10
複製程式碼
2.非同步剪裁圖片.
因為UIView本身並不是UIImage的容器, 所以不太容易直接放,
新增一個UIImageView蓋在上面, 在非同步繪製出當前cell, 並放入.
結果喜人, 幀數提高到了60幀附近了.
複製程式碼
這裡又有之前的前輩教導的常識:CALayer比UIView更輕量,
所以不需要響應互動的地方用CALayer可以大幅提高效能.
將UIImageView換為CALayer, 並將圖片放入contents.
結果實際上並沒有更好, 也許是幀數已經快到極限了.
複製程式碼
UIView 結論
依然是, 螢幕裡圓角數量不多的情況下(15-), 不太需要想辦法, 大膽用吧.
螢幕圓角非常多, 可以使用我寫的這種方法, 但限制其實也挺多的,
背景色必須是純色.
當然最好的方法肯定是UI直接把陰影與圓角剪裁給你, 直接用,
雖然會有圖層混合運算, 但是其實對效能影響很微妙.
複製程式碼
https://github.com/syik/UIImageView-ZJRadius
喜歡的話給個喜歡或者關注一下 3Q~