iOS 圆角优化-上

2018-05-15  本文已影响49人  ltryee

圆角是iOS系统中常见的视觉样式,从系统图标到导航栏按钮,圆角无处不在。因为圆角是符合人类视觉安全体验的,圆角让人觉得舒适,而尖角在潜意识层次是具有伤害体验的,因为尖尖的东西总是有可能对人造成伤害的,所以我们更喜欢圆角。在iOS开发过程中,苹果提供了一种添加圆角的方法,简单暴力有效,但并不是所有的开发者都清楚原理,因此设置圆角有时会带来一定的性能损耗。本文将从理论上介绍设置圆角方法,性能损耗的原因这两方面展开讨论。下一篇文章将从具体项目的实践中介绍如何避免性能损耗。

一种设置圆角的简单方法

在iOS开发过程中,有一种非常简单的方法,只需一行代码,就可以给UIView加上圆角效果。

view.layer.cornerRadius = 5;

这一行代码并不会带来任何性能上的损耗,然而理想和现实是有差距的,并不是所有的UIView都可以只通过一行代码添加上圆角。我们来看苹果对cornerRadius这一属性的解释:

By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to YES causes the content to be clipped to the rounded corners.

在通常情况下,cornerRadius属性只应用于layer的背景色和边线。将masksToBounds属性设置为YES才能把内容按圆角形状裁剪。

也就是说,如果UIView中含有子视图,还需要设置masksToBounds属性为YES,才能实现圆角。于是代码变成了两行:

view.layer.cornerRadius = 5;
view.layer.masksToBounds = YES;

就是这一行设置masksToBounds的代码,让我们的显示帧率蹭蹭往下掉。如果屏幕中同时显示的圆角个数过多,就会明显感觉到卡顿和跳帧。这是为什么呢?

性能损耗:掉帧

如果我们打开模拟器的Color Offscreen-Rendered Yellow选项,运行代码后会发现,在我们绘制圆角的地方出现了黄色的标记。黄色标记出现的地方即离屏渲染

在解释离屏渲染之前,先来介绍一点背景知识:

UIView和CALayer的关系

简单地说,UIView是对CALayer的封装。CALayer包含三个基本视觉元素:border(属性包括宽度,颜色),background(属性包括颜色)和contents,其中contents必须是一个CGImage

回到UIView和CALayer的关系:CALayercontents负责显示内容,同时UIView为其提供内容,以及负责处理触摸等事件,参与响应链

WWDC 2012: iOS App Performance: Graphics and Animations

离屏渲染

关于离屏渲染的介绍,可以参考这篇文章。文中提到:

当使用圆角,阴影,遮罩的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所以就需要屏幕外渲染被唤起。

屏幕外渲染并不意味着软件绘制,但是它意味着图层必须在被显示之前在一个屏幕外上下文中被渲染(不论CPU还是GPU)。

所以当使用离屏渲染的时候会很容易造成性能消耗,因为在OPENGL里离屏渲染会单独在内存中创建一个屏幕外缓冲区并进行渲染,而屏幕外缓冲区跟当前屏幕缓冲区上下文切换是很耗性能的。

上文提到,cornerRadius属性只对前景框和背景色起作用,再看CALayer的结构,如果contents有内容或者内容的背景不是透明的话,还需要把这部分弄个角出来,不然合成的结果还是没有圆角,所以才要修改masksToBoundsYES(在UIView上对应的属性是clipsToBounds)。前些日子很热闹的圆角优化文章中的2篇指出是修改masksToBoundsYES而非修改cornerRadius才是触发离屏渲染的原因,但如果以Color Offscreen-Renderd Yellow的特征为标准的话,这两个属性单独作用时都不是引发离屏渲染的原因,他俩合体才是。

简单来说,卡顿和跳帧的原因是我们设置圆角的两行代码,触发系统对圆角进行离屏渲染,进而影响了帧率。

总结

  1. 离屏渲染使用不当会导致性能问题。
  2. 只设置cornerRadius时不会触发离屏渲染,仅适用于特殊情况:contents为空或者contents不会遮挡背景色圆角。
  3. 打开模拟器的Color Offscreen-Rendered Yellow选项,可以检测离屏渲染。
上一篇 下一篇

猜你喜欢

热点阅读