drawViewHierarchyInRect:afterScreenUpdates:延迟其他动画 [英] drawViewHierarchyInRect:afterScreenUpdates: delays other animations

查看:1028
本文介绍了drawViewHierarchyInRect:afterScreenUpdates:延迟其他动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我使用 drawViewHierarchyInRect:afterScreenUpdates:以获取我视图的模糊图像(使用Apple的 UIImage 类别 UIImageEffects )。

In my app, I use drawViewHierarchyInRect:afterScreenUpdates: in order to obtain a blurred image of my view (using Apple’s UIImage category UIImageEffects).

我的代码如下所示:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];
UIImage *im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
/* Use im */

我在开发过程中注意到我的许多动画都被延迟了在使用我的应用程序之后,即,与新应用程序的重新启动相比,我的视图在显着(但不到约一秒)暂停之后开始动画。

I noticed during development that many of my animations were delayed after using my app for a bit, i.e., my views were beginning their animations after a noticeable (but less than about a second) pause compared to a fresh launch of the app.

经过一些调试后,我注意到只需使用 drawViewHierarchyInRect:afterScreenUpdates:,屏幕更新设置为 YES 造成这种延误。如果在使用会话期间从未发送此消息,则永远不会出现延迟。使用 NO 进行屏幕更新参数也会使延迟消失。

After some debugging, I noticed that the mere act of using drawViewHierarchyInRect:afterScreenUpdates: with screen updates set to YES caused this delay. If this message was never sent during a session of usage, the delay never appeared. Using NO for the screen updates parameter also made the delay disappear.

奇怪的是这个模糊的代码是完全不相关的(据我所知)延迟动画。有问题的动画不使用 drawViewHierarchyInRect:afterScreenUpdates:,它们是 CAKeyframeAnimation 动画。仅发送此消息的行为(屏幕更新设置为 YES )似乎在我的应用程序中全局影响了动画。

The strange thing is that this blurring code is completely unrelated (as far as I can tell) to the delayed animations. The animations in question do not use drawViewHierarchyInRect:afterScreenUpdates:, they are CAKeyframeAnimation animations. The mere act of sending this message (with screen updates set to YES) seems to have globally affected animations in my app.

发生了什么事?

(我创建了说明效果的视频: 没有动画延迟。请注意导航栏中Check!语音气泡出现延迟。)

(I have created videos illustrating the effect: with and without an animation delay. Note the delay in the appearance of the "Check!" speech bubble in the navigation bar.)

我创建了一个示例项目来说明这个潜在的错误。 https://github.com/timarnold/AnimationBugExample

I have created an example project to illustrate this potential bug. https://github.com/timarnold/AnimationBugExample

我收到Apple的回复,证明这是一个错误。请参阅下面的答案

I received a response from Apple verifying that this is a bug. See answer below.

推荐答案

我使用了我的一张Apple开发者支持服务单向Apple询问我的问题。

I used one of my Apple developer support tickets to ask Apple about my issue.

事实证明这是一个确认的错误(雷达编号17851775)。他们对正在发生的事情的假设如下:

It turns out it is a confirmed bug (radar number 17851775). Their hypothesis for what is happening is below:


方法drawViewHierarchyInRect:afterScreenUpdates:尽可能在GPU上执行其操作,并且这项工作可能会在另一个进程的应用程序地址空间之外发生。将YES作为afterScreenUpdates:参数传递给drawViewHierarchyInRect:afterScreenUpdates:将导致Core Animation刷新任务和渲染任务中的所有缓冲区。正如您可能想象的那样,在这些情况下还会发生很多其他内部事情。工程理论认为它很可能是这个机器中与你所看到的效果有关的错误。

The method drawViewHierarchyInRect:afterScreenUpdates: performs its operations on the GPU as much as possible, and much of this work will probably happen outside of your app’s address space in another process. Passing YES as the afterScreenUpdates: parameter to drawViewHierarchyInRect:afterScreenUpdates: will cause a Core Animation to flush all of its buffers in your task and in the rendering task. As you may imagine, there’s a lot of other internal stuff that goes on in these cases too. Engineering theorizes that it may very well be a bug in this machinery related to the effect you are seeing.

相比之下,方法renderInContext:在你的应用程序中执行它的操作地址空间,不使用基于GPU的流程来执行工作。在大多数情况下,这是一个不同的代码路径,如果它适合您,那么这是一个合适的解决方法。此路由不如使用基于GPU的任务那样高效。此外,它不像屏幕截图那样准确,因为它可能会排除由GPU任务管理的模糊和其他核心动画功能。

In comparison, the method renderInContext: performs its operations inside of your app’s address space and does not use the GPU based process for performing the work. For the most part, this is a different code path and if it is working for you, then that is a suitable workaround. This route is not as efficient as it does not use the GPU based task. Also, it is not as accurate for screen captures as it may exclude blurs and other Core Animation features that are managed by the GPU task.

他们还提供了一种解决方法。他们建议代替:

And they also provided a workaround. They suggested that instead of:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];
UIImage *im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
/* Use im */

我应该这样做

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
/* Use im */

希望这对某人有用!

这篇关于drawViewHierarchyInRect:afterScreenUpdates:延迟其他动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆