首先,我知道关于此主题还有其他一些StackOverflow问题,但是我已经阅读了所有这些问题,但我仍然对如何处理我的情况感到困惑。如果您可以帮助澄清这一点,我可能会在这里遗漏一些明显的信息,将不胜感激!
我有一个应用程序正在做大量工作来使视图中的图像动画化-主要由许多图像组成,这些图像一次直线移动一秒或两秒。我考虑过首先将它们简化,在整个运动过程中都使用UIView animateWithDuration
动画。但是我发现这并没有给我太多力量来拦截,停止运动或检查运动的方向,所以我放弃了这一点。我的新方法是使用NSTimer,每秒发射20次,进行增量移动。这样,我也可以立即(几乎)干预以更改动画,停止动画或基于动画的距离等更新状态标签等。
首先...可能有比这更好的方法。随时提出更好的建议!
假设这是可以接受的,那么我现在的问题是,尽管发生了这些动画,但是我无法单击UI上的任何其他控件。我没有回应。这也不是只是缓慢或延迟-点击永远不会实现。看来NSTimer处理完全锁定了UI-但仅来自新的交互。我在计时器处理方法中对UI所做的更改很好,并且非常敏捷。
从我所读的内容来看,这不应该发生。但是,我也看到了对this question的评论,它说如果计时器处理很密集,那么它可能会锁定UI线程。我在这里看不到我的处理工作如此密集-当然没有资源请求,只是一些数据处理和动画处理一些对象的动画-但我可能对此并不重视。
我在这里有什么选择?起初我以为我可以创建一个新的线程来启动计时器。但是我记得读过,无论如何,UI更新必须在主线程上进行。为什么是这样?另外,这真的可以解决问题吗?我是否只是问太多设备来处理此计时器以及UI交互?还有其他我想念的东西吗?
任何和所有建议,将不胜感激。
编辑:
我刚刚找到了导致UI阻塞的原因。我将animateWithDuration
与块一起使用,但未设置选项。因此未设置UIViewAnimationOptionAllowUserInteraction
。我将其更改为设置此选项,并且我的UI现在很高兴响应。
话虽如此,我仍然会保留这个问题,以寻求有关我总体方法的具体建议。谢谢。
最佳答案
我会考虑使用CADisplayLink。从文档中:
CADisplayLink对象是一个计时器对象,它允许您的应用程序将其图形同步到显示的刷新率。
您的应用程序将创建一个新的显示链接,其中提供了一个目标对象和一个在屏幕更新时要调用的选择器。接下来,您的应用程序将显示链接添加到运行循环。
将显示链接与运行循环关联后,当需要更新屏幕内容时,将调用目标上的选择器。目标可以读取显示链接的时间戳属性,以检索显示上一帧的时间。例如,显示电影的应用程序可能使用时间戳来计算下一个要显示的视频帧。执行自己的动画的应用程序可以使用时间戳来确定显示的对象在下一帧中的显示位置和显示方式。 duration属性提供帧之间的时间量。您可以在应用程序中使用此值来计算显示的帧频,显示下一帧的大概时间,并调整绘图行为,以便及时准备好下一帧以显示。
您的应用程序可以通过将paused属性设置为YES来禁用通知。另外,如果您的应用程序无法在所提供的时间内提供帧,则可能要选择较低的帧速率。与跳过帧的应用程序相比,具有较慢但一致的帧速率的应用程序对用户而言看起来更平滑。您可以通过更改frameInterval属性来增加帧之间的时间(并降低视在帧速率)。
当您的应用程序完成显示链接时,应调用invalidate将其从所有运行循环中删除,并将其与目标解除关联。
CADisplayLink不应被子类化。
关于objective-c - 重复NSTimer锁定UI线程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6688627/