iOS圆角触发离屏渲染原理和时机

相信iOS开发者工作中经常会写到按钮btn.layer.cornerRadius = 50;btn.clipsToBounds = YES;,面试中会问到什么是离屏渲染,什么操作会触发离屏渲染,笔者以前去面试直接会回答设置阴影,遮罩,给按钮设置圆角加clipsToBounds会触发离屏渲染。这时候面试官微微一笑回去等消息吧。

那么设置btn.layer.cornerRadius = 50;btn.clipsToBounds = YES一定会触发离屏渲染吗?

答案是不一定,要看具体情况。下面我写几段代码给大家看一下,四个按钮在模拟器上运行

SE2模拟器上运行结果如上图

此时打开模拟器debug功能的Color off-screen Rendered(显示需要离屏渲染的视图部分),效果如下图

开启离屏渲染显示后

此时我们看到模拟器上面第一个第三个button使用了离屏渲染(颜色为淡黄色),第二个第四个没有使用离屏渲染。

那么问题来了,四个按钮明明都设置了btn.layer.cornerRadius = 50;btn.clipsToBounds = YES; 为什么只有1,3开启了离屏渲染呢?这个要先弄清楚离屏渲染原理

离屏渲染原理

iOS屏幕显示视图步骤正常为 GPU进行渲染 -> 帧缓存(frameBuffer)-> 视频控制器 -> 读取帧缓存区信息(位图bitmap)数模转化(数字信号处->模 拟型号) ->(逐⾏扫描)显示,但是有些时候视图的图层Layer比较复杂多不能一次性绘制放入帧缓存区的时候就需要开辟离屏渲染缓冲区存储渲染数据,等到一个视图所有图层绘制混合完成后再从离屏渲染缓冲区放入帧缓存区,然后交由屏幕显示。步骤为 GPU进行解码渲染 -> 离屏渲染缓存(offscreen-buffer)多图层渲染裁剪修改合并等操作 -> 帧缓存(frameBuffer)-> 视频控制器 -> 读取帧缓存区信息(位图bitmap)数模转化(数字信号处->模 拟型号) ->(逐⾏扫描)显示。

一个CALayer图层是由背景色backgroundColor、内容contents、边缘borderWidth&borderColor构成。如下图

cornerRadius的文档中明确说明对cornerRadius的设置只对 CALayer 的背景色backgroundColor和边框borderWidth&borderColor起作用,如果contents有内容或者内容的背景不是透明的话,只有设置masksToBounds为 true 才能起作用,此时两个属性相结合,产生离屏渲染。这也就说明了上面代码为什么1和3触发了离屏渲染,而2和4没有触发离屏渲染。

那么如何避免设置圆角触发离屏渲染呢?

1. 如果需要设置圆角,可以使用切好的圆角图片,或者自己使用贝塞尔曲线进行圆角绘制

2.如果button需要设置圆角,那么对button.imageview.clipsToBounds=yes也可以避免离屏渲染,这是iOS9以后苹果做的优化,如下图,我在代码中稍微修改了下


这样设置后可以看到第一张图片也没有触发离屏渲染。

你可能感兴趣的:(iOS圆角触发离屏渲染原理和时机)