ios 离屏渲染和异步绘制,为什么要离屏渲染

  ios 离屏渲染和异步绘制,为什么要离屏渲染

  

Python实战社群

  

Java实战社群

  

长按识别下方二维码,

按需求添加

  

扫码关注添加客服

  

进Python社群

  

扫码关注添加客服

  

进Java社群

  作者丨收納箱

  来源丨掘金

  链接:

  https://juejin.im/post/5f0339505188252e817c6c02

  测试环境

  Xcode 11.4

  iPhone 11 Pro

  iOS 13.5

  

1. 如何设置圆角才会触发离屏渲染

我们经常看到,圆角会触发离屏渲染。但其实这个说法是

不准确的

,因为圆角触发离屏渲染也是

有条件

的!

  我们先来看看苹果官方文档对于拐角半径的描述:

  将半径设置为大于0.0的值会导致图层开始在其背景上绘制圆角。默认情况下,圆角半径不适用于图层内容属性中的图像;它仅适用于图层的背景色和边框。但是,将masksToBounds属性设置为真实的会导致内容被裁剪为圆角。

  我们发现设置拐角半径大于0时,只为层的背景颜色和边界设置圆角;而不会对层的内容设置圆角,除非同时设置了layer.masksToBounds为真(对应自定义的剪辑边界属性)。

  如果这时,你认为layer.masksToBounds或者剪辑边界设置为真实的就会触发离屏渲染,这是不完全正确的。

  我们先打开模拟器的离屏渲染颜色标记:

  不设置layer.masksToBounds或者clipsToBounds,其默认值为不

  -(void)viewDidLoad {[super viewDidLoad];ui view * view 1=[[ui view alloc]initWithFrame:CGRectMake(0,0,200.0,200.0)];//设置背景色观点1。背景色=用户界面颜色。红色;//设置边框宽度和颜色观点1。层。边框宽度=2.0;观点1。层。边框颜色=用户界面颜色。黑色。CG颜色;//设置圆角观点1。层。拐角半径=100.0;观点1。中心=自我。查看。居中;【自我。view addSubview:view 1];}

  我们看到只有背景色、边框以及圆角的时候,确实不会触发离屏渲染。

  设置layer.masksToBounds或者剪辑边界为是

  -(void)viewDidLoad {[super viewDidLoad];ui view * view 1=[[ui view alloc]initWithFrame:CGRectMake(0,0,200.0,200.0)];//设置背景色观点1。背景色=用户界面颜色。红色;//设置边框宽度和颜色观点1。层。边框宽度=2.0;观点1。层。边框颜色=用户界面颜色。黑色。CG颜色;//设置圆角观点1。层。拐角半径=100.0;//设置裁剪观点1。剪辑到边界=是;观点1。中心=自我。查看。居中;【自我。view addSubview:view 1];} 当我们开启layer.masksToBounds或者剪辑边界时,同样的没有触发离屏渲染。这是因为我们还没有设置图片。

  设置layer.masksToBounds或者剪辑边界为是的,同时设置图片

  -(void)viewDidLoad {[super viewDidLoad];ui view * view 1=[[ui view alloc]initWithFrame:CGRectMake(0,0,200.0,200.0)];//设置背景色观点1。背景色=用户界面颜色。红色;//设置边框宽度和颜色观点1。层。边框宽度=2.0;观点1。层。边框颜色=用户界面颜色。黑色。CG颜色;//设置图片观点1。层。contents=(_ _ bridge id)[ui image image name:@ pkq ].CGImage//设置圆角观点1。层。拐角半径=100.0;//设置裁剪观点1。剪辑到边界=是;观点1。中心=自我。查看。居中;【自我。view addSubview:view 1];} 当我们开启layer.masksToBounds或者剪辑边界时,同时设置图片时,就会触发离屏渲染。

  其实不光是图片,我们为视图添加一个有颜色、内容或边框等有图像信息的子视图也会触发离屏渲染。

  

有图像信息

还包括在视图或者层的画方法中进行绘制等。

  -(void)viewDidLoad {[super viewDidLoad];ui view * view 1=[[ui view alloc]initWithFrame:CGRectMake(0,0,200.0,200.0)];//设置背景色view 1 . background color=ui color . red color;//设置边框宽度和颜色view 1 . layer . border width=2.0;view 1 . layer . border color=ui color . black color . CG color;//设置圆角view 1 . layer . corner radius=100.0;//设置剪辑view1.clipsToBounds=YES//子视图ui view * view 2=[[ui view alloc]initwithframe:cgrectmake(0,0,100.0,100.0)];//以下三个属性中的任意一个//设置背景色view 2 . background color=ui color . blue color;//设置内容view 2 . layer . contents=(_ _ bridge id)([UI image named:@ pkq ]。cgimage);//设置边框view 2 . layer . border width=2.0;view 2 . layer . border color=ui color . black color . CG color;[视图1添加子视图:视图2];view 1 . center=self . view . center;[self . view addSubview:view 1];}

  

2. 圆角触发离屏渲染的真正原因

层的叠加图大概遵循“画家算法”。

  

油画算法

:先画场景中离观察者较远的物体,再画较近的物体。

  先画红色部分,再画彩色部分,最后画灰色部分,可以解决消隐面的问题。即根据物理距离和观察者的距离对场景进行排序,可以从远到近进行绘制。

  当为拐角裁剪设置cornerRadius和masksToBounds时,masksToBounds裁剪属性将应用于所有图层。

  我们以前是从后往前画,画完一层就可以丢弃了。但是现在需要依次保存在

Offscreen Buffer

,等待切圆角过程,也就是

离屏渲染

被触发。

  背景色,边框,背景色边框,加圆角切割。根据文档,masksToBounds设置为YES或NO并不重要,因为在

contents = nil

中没有任何内容需要删除。

  一旦我们做出

为contents设置了内容

,无论是图片,绘图内容,带图像信息的子视图等。加上圆角裁剪,会触发离屏渲染。

  不一定要直接给内容赋值!

  

3. iOS9及以后的优化

苹果对圆角、iOS 9及以后的系统版本做了一些优化。

  图层.内容/图像视图.图像

  我们只设置了contents或者UIImageView的图像,加上圆角,不会产生离屏渲染。但是,如果添加了背景色、边框或其他包含图像内容的图层,仍然会出现离屏渲染。

  -(void)viewDidLoad {[super viewDidLoad];ui view * view 1=[[ui view alloc]initWithFrame:CGRectMake(0,0,200.0,200.0)];//设置图片view 1 . layer . contents=(_ _ bridgeid)[ui image named:@ qiyu ]。cgimage//设置圆角view 1 . layer . corner radius=100.0;//设置剪辑view1.clipsToBounds=YESview 1 . center=self . view . center;[self . view addSubview:view 1];}

  其实这也是可以理解的,因为只有

单层

的内容需要进行圆角裁剪,所以不需要屏外渲染技术。但是,如果添加了背景色、边框或其他有图像内容的图层,

多层

会被四舍五入和裁剪,所以仍然会触发离屏渲染(比如1中的第三个例子)。

  所以,我们在使用类似UIButton的视图时需要注意:

  

UIButton

  -(void)viewDidLoad {[super viewDidLoad];self . view . background color=[ui color white color];//创建按钮视图ui button * button=[[uibuttonalloc]initwithframe:cgrectmake(0,0,200.0,200.0)];//设置图片[Button SetImage:[UI Image Named:@ PKQ ]for state:UIControlStateNormal];button . center=self . view . center;[self . view addSubview:button];}

  当我们为UIButton设置图片时,实际上会添加一个UIImageView。

  向UIButton添加圆角和裁剪将触发离屏呈现。

  I//设置圆角button.layer.corner半径=100.0;//设置剪辑按钮. button.clipsToBounds=YES

  

不会触发离屏渲染

如果在UIButton中更改为UIImageView添加圆角和裁剪。

  //设置rounded button . imageview . layer . corner radius=100.0;//设置剪辑按钮. button.imageview.clipstobonds=yes复制代码

  要了解更多关于渲染问题的信息,您可以阅读下面的文章。

  iOS渲染原理分析

  作者储物盒

  链接 3359juejin.im/post/5f0339505188252e817c6c02

  程序员专栏扫码关注添加客服长按识别下方二维码进群

  

近期精彩内容推荐:

  

哈工大大四学生被开除,痛失知名大厂Offer

  

有个程序员老公有多爽???

  

碉堡了!一款专门为程序员的编程字体!

  

助你进大厂,这些知识你是必须知道的。

  

在看点这里

好文分享给更多人

  如何在CSS中设置div滚动条的样式

ios 离屏渲染和异步绘制,为什么要离屏渲染