1

我有一个UITableViewCell其中里面有 5 个UILabelaUIButton和一个UIImageView填充单元格作为背景的 a。性能似乎有点慢,所以我正在考虑使用CoreGraphics它来改进它。CoreGraphics使用而不是UILabelassubViews会让事情变得更快,这是真的吗?如果是,为什么?

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

[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]];
4

3 回答 3

3

一般来说,(正如 Gavin 指出的那样)我会说你必须首先确认子视图确实导致滚动时出现抖动。

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

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

另外值得注意的是——要意识到绘制阴影的成本很高,并且根据您的实现,它们可能会在每一帧上重新绘制!您最好的选择是确保任何 CALayer 阴影都完全光栅化,并定义了路径,因此不必从像素蒙版进行实时计算。

如果最终,您确定每个子视图的布局和重绘单独导致速度变慢,那么我有几点/解释:

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

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

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

于 2012-12-07T19:05:47.460 回答
2

在模拟器上,DebugColor Blended Layers。红色是坏的,绿色是好的。

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

在深入研究 Core Graphics 之前,您应该考虑三个修复(所有这些都减少了红色的数量):

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

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

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

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

于 2012-12-07T20:14:21.433 回答
1

您有什么证据表明您的观点导致了性能问题?这是一个可以把你吸进去的深黑洞,所以要确保你知道问题出在你认为的地方。

您是否正在预加载所有数据?你有没有预下载图片?你所描述的不应该导致 UITableViewCell 变慢。Apple 开发人员比你聪明得多,所以我要确保你有数据来支持你的决定!

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

确实,使用 CoreGraphics 可以加快您的绘图性能,但如果您做错了,它也会减慢它的速度!查看Apple 高级表格视图单元教程,了解如何执行该技术。

于 2012-12-07T18:17:51.700 回答