UIKit性能调优实战讲解
总结
避免图层混合
- 确保控件的opaque属性设置为true,确保backgroundColor和父视图颜色一致且不透明
- 如无特殊需要,不要设置低于1的alpha值
- 确保UIImage没有alpha通道
避免临时转换
- 确保图片大小和frame一致,不要在滑动时缩放图片
- 确保图片颜色格式被GPU支持,避免劳烦CPU转换
慎用离屏渲染
- 绝大多数时候离屏渲染会影响性能
- 重写drawRect方法,设置圆角、阴影、模糊效果,光栅化都会导致离屏渲染
- 设置阴影效果是加上阴影路径
- 滑动时若需要圆角效果,开启光栅化
- 为什么要把控件尽量设置成不透明的,如果是透明的会有什么影响,如何检测这种影响?
注解:
很多文章里说把控件设置为opaque = true,其原理就是希望避免图层混合,然而这种调优一般情况下用处不大。因为UIView的opaque属性默认值就是true,也就是说只要不是人为设置成透明,都不会出现图层混合。
个人认为比opaque属性更重要的是backgroundColor属性,如果不设置这个属性,控件依然被认为是透明的,所以我们做的第一个优化是在CustomTableCell类的init方法中添加一行代码:
label.backgroundColor = UIColor.whiteColor()
- 为什么cell中的图片,尽可能要使用正确的大小、格式,如果错误会有什么影响,如何检测这种影响?
- 为什么设置阴影和圆角有可能影响滑动时流畅度?
- shouldRasterize和离屏渲染的关系是什么,何时应该使用?
光栅化
光栅化是将一个layer预先渲染成位图(bitmap),然后加入缓存中。如果对于阴影效果这样比较消耗资源的静态内容进行缓存,可以得到一定幅度的性能提升。demo中的这一行代码表示将label的layer光栅化:
label.layer.shouldRasterize = true
颜色格式
图片大小
在demo中,每个UIImageView的大小都是180x180,而只有第二张图片的像素大小是360x360。因此除了第二张图片,其他的图片都需要被缩放。
图片的缩放需要占用时间,因此我们要尽可能保证无论是本地图片还是从网络或取得图片的大小,都与其frame保持一致
第三个优化是调整所有图片的像素大小以避免不必要的缩放。
离屏渲染
离屏渲染可能会自动触发,也可以手动触发。以下情况可能会导致触发离屏渲染:
- 重写drawRect方法
- 有mask或者是阴影(layer.masksToBounds, layer.shadow*),模糊效果也是一种mask
- layer.shouldRasterize = true
前两者会自动触发离屏渲染,第三种方法是手动开启离屏渲染。
使用了阴影,接下来我们进行第四个优化,在设置阴影效果的四行代码下面添加一行:
imgView.layer.shadowPath = UIBezierPath(rect:imgView.bounds).CGPath
这行代码制定了阴影路径,如果没有手动指定,Core Animation会去自动计算,这就会触发离屏渲染。
如果人为指定了阴影路径,就可以免去计算,从而避免产生离屏渲染。
设置cornerRadius本身并不会导致离屏渲染,但很多时候它还需要配合layer.masksToBounds = true使用。
根据之前的总结,设置masksToBounds会导致离屏渲染。
解决方案是尽可能在滑动时避免设置圆角,如果必须设置圆角,可以使用光栅化技术将圆角缓存起来:
// 设置圆角
label.layer.masksToBounds = true
label.layer.cornerRadius = 8
label.layer.shouldRasterize = true
label.layer.rasterizationScale = layer.contentsScale
转载:https://bestswifter.com/uikitxing-neng-diao-you-shi-zhan-jiang-jie/