提高自定义 UIView 的绘图性能
我有一个自定义的 UIView,它由许多图像组成,它们的位置随着用户触摸而变化。 该视图必须跟踪用户触摸,而我在绘制此类视图时遇到性能瓶颈,导致我无法实时跟踪输入。
一开始,我在 [UIView drawRect:] 方法中绘制所有内容,当然它太慢了,因为即使没有必要,所有内容都会重新绘制。 然后,我使用更多的 CALayers 来仅更新正在更改的层,这给了我更好的响应能力。 但是,当我必须在一个图层上多次绘制相同的图像时,最多需要 500 毫秒。
由于图像放置在固定位置,是否有办法预先绘制它们?我是否应该考虑将它们放入多个 CALayers 中并隐藏/显示它们? 另外,我不明白为什么存在 [CALayer setNeedsDisplayInRect:]
但委托(显然)无法知道无效的矩形是什么来优化绘图。
解决方案
按照答案中的建议,我最终为图像创建了许多 CALayers,并在第一次显示图层时设置了 contents
属性。这是一种延迟加载的妥协:在第一次尝试中,我在创建时设置了每个图层的内容,但这导致在程序启动时预先绘制任何可能的图像,从而将应用程序冻结几秒钟。
I have a custom UIView which is composed of many images, their positions are changing in response to the user touch.
The view must track the user touch and i'm experiencing a performance bottleneck in the drawing of such view, preventing me to follow the input in realtime.
At the beginning i was drawing everything in the [UIView drawRect:]
method and of course it was way too slow because everything was redrawn even if not necessary.
Then, i used more CALayers to update only the layer that was changing and this gave me much better responsiveness.
But still, when i have to draw the same image many times on a layer it takes up to 500ms.
Since the images are placed at fixed positions it there a way to pre-draw them? Should i consider putting them in many CALayers and just hide/show them?
Also, i don't understand why a [CALayer setNeedsDisplayInRect:]
exists but the delegate has (apparently) no way to know what the invalid rect is to optimize the drawing.
Solution
Following the advice in the answer I finally created many CALayers for the images and set the contents
property the first time the layer was being shown. This is a lazy-loading compromise: in a first attempt i set the contents of every layer at the creation time but this caused to pre-draw any possible image on the program launch, freezing the application for seconds.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自 -[CALayer drawInContext:] 的文档:
显示的默认实现在自动创建的上下文上调用drawInContext:;大概也设置了边界框(大概被传递给drawRect:)。
如果您要绘制多张静态图像,我只需将每张图像粘贴到其自己的 UIView 中即可;我不认为开销有那么大(如果是的话,CALayer 开销应该更小)。如果它们都有动画,我肯定会使用 UIView/CALayer。如果其中一些动画没有(太多)并且您发现速度明显缓慢,则可以预渲染它们。这是在drawRect:(或类似的)中渲染和GPU上的图层合成之间的权衡,但总的来说,我认为后者要快得多。
From the documentation for -[CALayer drawInContext:]:
The default implementation of display calls drawInContext: on an automatically-created context; presumably setting the bounding box as well (which is presumably passed to drawRect:).
If you're drawing several static images, I'd just stick each one in its own UIView; I don't think the overhead is that big (if it is, the CALayer overhead should be smaller). If they all animate, I'd definitely use UIView/CALayer. If some of them don't animate (much) and you notice significant slowness, you can pre-render those. It's a trade-off between rendering in drawRect: (or similar) and layer compositing on the GPU, but in general I'd assume that the latter is much faster.