在后台线程上渲染新的 UIView 图层内容?

Posted

技术标签:

【中文标题】在后台线程上渲染新的 UIView 图层内容?【英文标题】:Rendering new UIView layer contents on background thread? 【发布时间】:2012-08-09 03:13:48 【问题描述】:

我有一大堆旋转动画 UIView 实例,它们的内容设置为各种 CGImage ,它们都是(并且本质上需要)动态创建的。它工作得很好,但图像生成速度很慢(大约 1/4 秒到 1 秒,即不可接受)。

所以我想做的是非常快速地生成一个低分辨率近似值(比如 1/100 秒),并将 UIView 的 CALayer 的内容(例如,view.layer.contents)设置为那个快速的低分辨率图像,然后立即生成一个后台线程以生成高分辨率版本,并在准备好后立即替换低分辨率版本。

有哪些合理的方法可以做到这一点?

我的想法是我应该使用GCD(Grand Central Dispatch)来调度后台线程,然后在完成后再次使用它来发送消息。如果我这样做,将新的高分辨率替换图像作为完成消息的一部分发送是否有意义?

如果我需要取消后台线程怎么办?如果用户向前翻页到不同的对象,就会发生这种情况,在这种情况下,我将不得不取消当前的后台任务并为不同的视图启动一个新任务。 (这实际上是一个相当普遍的情况,所以我肯定需要处理它。)我不认为我可以杀死后台任务,因为它可能正在处理 CGPath、CGGradient、CGImage 等对象那将需要被释放。有哪些方法可以从一个线程设置另一个线程可以测试的标志?我是否应该从主线程向后台线程发送某种“中止”信号,然后让后台线程在最舒适的位置自行中止创建图像?

【问题讨论】:

观看会话 211 - 在 ios 上构建并发用户界面,来自 WWDC 2012。它有很多信息可以直接解决您的问题。您可能还想查看会话 235 和 238。 酷,我刚看完#211。 NSOperationQueue 听起来像是要走的路,可能。谢谢。 感谢 rob mayoff,看完 Session 211,我解决了我的 UITableView 性能问题! 【参考方案1】:

我不会为此使用 GCD。 GCD 在回调中更新 UI 时出现问题。如果按图像执行此操作,则会破坏性能。只需分离一个线程并实现高清图像在每次渲染其中一个图像时串行执行回调。它更简单,您对主线程的回调将显示得更快。

出于某种原因,来自 GCD 的 UI 更新似乎不太可靠,因为速度太慢了。不知道为什么会这样。

【讨论】:

好吧,我不是在想辅助线程会更新 UI,而是辅助线程会在完成后向主线程发送一条消息(包含完成的图像)​​,然后主线程会更新用户界面。 是的,确实如此,它必须这样做,但 GCD 效率不高,因为这个原因我不得不删除 GCD 代码。 [self performSelectorOnMainThread:@selector(update:) withObject:value waitUntilDone:NO];从后台线程工作得很好

以上是关于在后台线程上渲染新的 UIView 图层内容?的主要内容,如果未能解决你的问题,请参考以下文章

iOS:主线程检查器:在后台线程上调用的 UI API:-[UIView retainCount]

iOS核心动画Core Animation

让 UIView drawRect 发生在后台线程中

iPhone - 在 UITableView 上拖动会在后台停止渲染 OpenGL

如何在drawRect中获取UIView大小

CALayer动画