Swift: 运行 代码阻止其他代码直到完成

Swift: Running code prevents other code until completed

我在 ViewDidAppear 中调用一个动画,稍后在 ViewDidAppear 中我调用一个创建多个 UIImage 对象数组并需要 4-5 秒才能完成的函数。

同时,动画只有 0.8 秒长,并且有一个完成块:

UIView.animate(withDuration: 0.8, delay: 0.0, options: UIViewAnimationOptions(), animations: {
            self.myView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
        }, completion: { finished in
            self.nextTask()
        })

问题是完成块不会在 运行 0.8 秒后 - 它不会 运行 直到前面的代码完成。

除了 运行 DispatchQueue.global(qos: .background).async 在后台线程中编写代码外,我还有什么可以做的吗?或者有没有办法提高后台线程的完成速度?

如果在后台线程中完成,我的动画不会被打断,但在后台完成需要更长的时间——比如 20-30 秒而不是 4-5 秒。

感谢您在这里分享任何帮助!

I am calling a function which creates several arrays of UIImage objects and takes 4-5 seconds to complete

你绝对不能 运行 在主线程上这样做。现代设备上的刷新帧为 1/120 秒。您不得导致帧丢失。发生这种情况时,您正在阻止用户交互。屏幕将被冻结,看门狗进程将当场杀死您的应用程序。 (不幸的是,模拟器没有向您显示,设备上的 运行ning from Xcode 也没有显示;但是如果您 运行 设备上的应用程序,请停止它,然后 运行 它 来自设备 而不是来自 Xcode,你会明白我的意思。)

The issue is that the completion block doesn't run 0.8 seconds later - it doesn't run until AFTER the previous code completes.

如您所料,此处存在重入问题。您需要离开主线程以允许完成块发生。我真的很惊讶动画甚至 starts(是吗?)。当您仍在主线程上 运行 宁代码时,什么都不会发生。

您可以调用 async_after 以短暂延迟暂时跳出主线程,然后重新进入主线程,足够长的时间让刷新帧发生,这样系统就可以做一些工作。但这只是让动画开始的一种方式。回到主线程后,您将再次阻塞它。

至于速度:.background 的 QOS 是 最慢的 选择,因此您得到了您想要的。不过,一般来说,不要使用全局队列;制作自己的队列。我无法想象你正在做的事情会花这么长时间,也许这才是你真正应该问的问题,但你绝对不能在主线程上做。