离屏渲染的感念:
离屏渲染(offscreen-rendering)顾名思义为屏幕外的渲染,即渲染的结果不会直接呈现到当前屏幕上,而是等待合适的时机才会被显示。
离屏渲染代价主要两个方面:(1)创建新缓冲区 (2)上下文切换
离屏渲染触发:
(1)被动触发:圆角(圆角单纯的设置 cornerRadius 并不会触发离屏渲染,需要配合 masksToBounds 切割边缘之外的子视图)、以及 iOS 9 之前图片的圆角、阴影、遮罩(mask)、模糊。重写-drawRect方法,视图只要设置背景颜色,也会触发离屏渲染。(2)主动触发离屏渲染的方式是利用 CALayer.shouldRasterize 属性,开启光栅化。光栅化是一个比较抽象的概念,它的作用是强制将 CALayer 以 bitmap 的形式进行缓存,等价于屏幕外的缓存,也属于离屏渲染的概念。
离屏渲染触好处:利用 CALayer.shouldRasterize 开启光栅化,将离屏渲染的内容以位图的形式缓存,减少复杂视图频繁渲染的开销。
优化方案:
(1)使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角。
(2)使用CAShapeLayer和UIBezierPath设置圆角
(3)shadow优化 :可以通过设置shadowPath来优化性能,能大幅提高性能
其他方案:1.当我们需要圆角效果时,可以使用一张中间透明图片蒙上去。
2.使用ShadowPath指定layer阴影效果路径。
3.使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)。
4.设置layer的opaque值为YES,减少复杂图层合成。
5.尽量使用不包含透明(alpha)通道的图片资源。
6.尽量设置layer的大小值为整形值。
7.直接让美工把图片切成圆角进行显示,这是效率最高的一种方案。
8.很多情况下用户上传图片进行显示,可以让服务端处理圆角。
9.使用代码手动生成圆角Image设置到要显示的View上,利用UIBezierPath(CoreGraphics框架)画出来圆角图片。
pragma mark-上圆角
+(void)masksTopRadius:(UIView*)topView radius:(CGFloat )radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:topView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = topView.bounds;
maskLayer.path = maskPath.CGPath;
topView.layer.mask = maskLayer;
}
pragma mark-下圆角
+(void)masksBelowRadius:(UIView*)belowView radius:(CGFloat )radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:belowView.bounds byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = belowView.bounds;
maskLayer.path = maskPath.CGPath;
belowView.layer.mask = maskLayer;
}
pragma mark-圆角
+(void)bezierPathIconView:(UIView *)iconView{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:iconView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:iconView.bounds.size];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
//设置大小
maskLayer.frame = iconView.bounds;
//设置图形样子
maskLayer.path = maskPath.CGPath;
iconView.layer.mask = maskLayer;
}
//欢迎加入:洛阳iOS开发交流(570890454)
网友评论