CoreGraphics(drawRect)用于在UITableViewCell中绘制标签和UIImageView

时间:2012-12-07 18:14:20

标签: ios iphone objective-c uitableview core-graphics

我有UITableViewCell其中有UILabelUIButtonUIImageView,其中填充了单元格作为背景。性能似乎有点慢,所以我想用CoreGraphics来改进它。使用CoreGraphics代替UILabel作为subViews会使事情变得更快吗?如果是,为什么?

我有以下代码在单元格上绘制阴影:

[self.layer setBorderColor:[UIColor blackColor].CGColor];
[self.layer setShadowColor:[UIColor blackColor].CGColor];
[self.layer setShadowRadius:10.0];
[self.layer setCornerRadius:5.0];
[self.layer setShadowPath:[[UIBezierPath bezierPathWithRect:self.frame] CGPath]];

3 个答案:

答案 0 :(得分:3)

一般来说,(正如Gavin指出的那样)我会说你必须首先确认子视图确实在你的滚动中引起了抖动。

当我测试UITableViewCell滚动性能时,我经常使用仪器中的Time Profiler。切换到Objective-C仅在左侧面板中,查看主线程上花费最多时间的内容。如果您在重新排列(布局)或绘制子视图上花费了大量时间,则可能需要使用CoreGraphics。如果将时间花在分配/解除分配上,那么您可能想要检查子视图的重用方式(如果有的话)。如果它们没有被重用,那么这当然会导致性能问题。

然后,当然,你应该看看合成。如果您的子视图不是不透明的(通过CoreAnimation工具识别),那么性能可能会受到严重影响。

同样值得注意的是 - 意识到阴影的绘制成本很高,并且根据您的实现,它们可能会在每一帧上重绘!您最好的选择是确保任何CALayer阴影都完全光栅化,并且定义了一个路径,以便不必进行像素掩模的实时计算。

如果最后,你确定每个子视图的布局和重新绘制都会导致速度减慢,那么我有几点/解释:

  1. 您对表格视图单元格的绘图例程的实现可能比Apple为其视图编写的高度优化的绘图要慢。所以你不会赢得任何重新实现UIImageView本身绘图的战斗。使用CoreGraphics绘制时,性能提升来自两个地方:a。)预先渲染以前非不透明的视图,并减少在视图绘制周期的布局阶段花费的时间 - 这减少了GPU / CPU上的工作负载滚动。 b。)减少单个视图绘制的时间切换CG上下文。现在,每个元素同时绘制到相同的图形上下文中,从而降低了转换成本。

  2. 在主线程上使用CoreGraphics绘制drawRect使用CPU绘制,并且根据您的单元格的复杂程度,这可能会导致其自身的抖动。相反,考虑在后台线程中绘制一个单独的CGContext,然后调度一个worker将图形内容作为CGImageRef插入到CALayer中,或者作为UIImageView中的UIImage插入。 GitHub上有一个天真的实现:https://github.com/mindsnacks/MSCachedAsyncViewDrawing

  3. 如果您决定使用后台CoreGraphics绘图,请注意,目前(2012年12月),我相信在使用后台线程绘制背景线程时,NSString绘图类别中存在一个错误这绝对不是线程安全的。这将导致崩溃,因此目前,请确保异步绘图在串行GCD / NSOperation队列中完成。

答案 1 :(得分:2)

在模拟器上,调试颜色混合图层。红色是坏的,绿色是好的。

更准确地说,红色意味着GPU需要进行alpha混合。主要成本是绘制像素两次所需的内存带宽,并可能重新获取额外的纹理。完全透明的像素真的坏。

三个修复(所有这些都会减少红色),在进入Core Graphics之前应该考虑这些修复:

  • 尽可能使视图不透明。背景设置为[UIColor clearColor]的标签通常可以设置为平面颜色。
  • 使透明度尽可能小的视图。对于标签,这涉及使用-sizeToFit/-sizeThatFits:并适当调整布局。
  • 从不透明图像中删除Alpha通道(例如,如果您的单元格背景是图像) - 某些图像编辑器不执行此操作,这意味着GPU需要执行alpha测试,并且可能需要渲染图像背后的任何内容

此外,打开和彩色屏幕外渲染(可能在关闭颜色混合图层后,以便更容易看到)。屏幕外渲染的内容显示为黄色,通常表示您已应用图层蒙版。这些可能对性能非常不利;我不知道CoreAnimation是否缓存了掩码结果。

最后,您可以通过设置cell.layer.shouldRasterize = YES(在视网膜设备上也可能需要cell.layer.rasterizationScale = [[UIScreen mainScreen].scale)使CoreAnimation光栅化单元格;如果这是自动完成,我会忘记。主要的好处是它很容易,而且比在Core Graphics中自己渲染图像视图更有效。 (由于文本需要在CPU上呈现,因此减少了标签的好处。)

另请注意,观看动画会受到影响。我忘记了CALayer.shouldRasterize的设置(它可能会在动画的每一帧重新光栅化它,当它只被绘制到屏幕一次时会有点浪费),但使用Core Graphics会(默认情况下)拉伸渲染动画期间的内容。见CALayer.contentsGravity。

答案 2 :(得分:1)

您有什么证据表明您在观点中所拥有的内容会导致性能问题?这是一个深黑洞,可以吸引你,所以一定要知道问题出在你想象的地方。

您是否在预加载所有数据?你有预先下载的图片吗?你所描述的不应该导致UITableViewCell的速度减慢。 Apple developers are much smarter than you and I所以请确保您已获得数据来支持您的决定!

我在模拟器中也看到了一个滞后的UITableViewCell,在真实硬件上没有明显区别。

使用CoreGraphics确实可以加快你的绘图性能,但如果你做错了它也可以减慢它的速度!请查看Apple Tutorial on Advanced Table View Cells如何执行该技术。