在2011年的WWDC视频会议121中,为了提高UI性能,演讲者选择使用UIBezierPath在drawRect:中绘制圆角,而不是直接在图层上设置圆角半径。
为什么使用UIBezierPath进行绘制一定更快?因为drawRect:发生在软件中,可能也很慢。
在2011年的WWDC视频会议121中,为了提高UI性能,演讲者选择使用UIBezierPath在drawRect:中绘制圆角,而不是直接在图层上设置圆角半径。
为什么使用UIBezierPath进行绘制一定更快?因为drawRect:发生在软件中,可能也很慢。
简短回答:在没有性能问题之前,最好使用CALayer的cornerRadius。
长话短说:
我们首先需要区分“绘画”和“合成”。
iOS上的绘画是将纹理用像素填充的简单行为(一个受CPU限制的任务)。合成是将所有这些纹理压平成一个单独的帧以打印到屏幕上的操作(一个受GPU限制的任务)。一般来说,在滚动或动画时,你主要会消耗GPU资源,这是好事,因为像将所有像素向下移动一个像素之类的操作对于GPU而言轻而易举。
-drawRect: 是纯粹的绘图,使用CPU填充纹理。CALayer的cornerRadius是在合成阶段完成的,会给GPU带来压力。
使用-drawRect: 有很高的初始成本(它可能比一个帧还要长),并且内存使用量相当大,但之后滚动非常流畅(现在它只是像任何其他纹理一样的纹理)。使用CALayer的cornerRadius创建一堆具有圆角的视图非常快,但一旦你拥有超过十几个视图,你就可以忘记滚动速度了(因为GPU不仅需要执行正常的滚动任务,还需要不断地添加圆角到你的视图中)。
但是不要轻信我的话,看一些数字数据。我改编了Florian Kugler的基准测试,并在运行iOS 6.1.3的iPhone 4S上进行了测试。我测量了在1/60秒内最多可以创建多少个视图,然后测量了在帧率低于60fps之前可以动画显示多少个视图。换句话说:初始成本与帧速成本的对比。
| -drawRect: | CALayer’s cornerRadus 16.6ms内渲染的最大视图数 | 5 views | 110 views 以60fps动画显示的最大视图数 | ~400 views | 12 views
(请注意,当500个-drawRect:视图使用太多内存时,应用程序会被终止)
归根结底,在我的项目中,我倾向于尽可能多地使用CALayer的cornerRadius。 我很少需要具有圆角的几个视图,并且-drawRect:具有太大的初始性能损失。 而为了使角落变圆而子类化一个视图只是一种非常讨厌的方法。
无论您选择哪种方法,请确保测量和关注您的应用程序的流畅性和响应能力,并据此做出相应的反应。