Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 具有DispatchGroup的异步函数_Swift - Fatal编程技术网

Swift 具有DispatchGroup的异步函数

Swift 具有DispatchGroup的异步函数,swift,Swift,我正在尝试在操场内设置动画,并在完成后在调试器中弹出一条简单消息 这样,.notify就会出现在开头。当动画函数在DispatchQueue.main.async(组:animationGroup)内部运行后,它不会出现吗 以下是提供的代码: import UIKit import PlaygroundSupport PlaygroundPage.current.needsIndefiniteExecution = true extension UIView { static func a

我正在尝试在操场内设置动画,并在完成后在调试器中弹出一条简单消息

这样,.notify就会出现在开头。当动画函数在DispatchQueue.main.async(组:animationGroup)内部运行后,它不会出现吗

以下是提供的代码:

import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

extension UIView {
  static func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void, group: DispatchGroup, completion: ((Bool) -> Void)?) {
     
  }
}
let animationGroup = DispatchGroup()
// A red square
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = UIColor.red
// A yellow box
let box = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
box.backgroundColor = UIColor.yellow
view.addSubview(box)
PlaygroundPage.current.liveView = view

DispatchQueue.main.async(group: animationGroup) {

  UIView.animate(withDuration: 1, animations: {
    // Move box to lower right corner
    box.center = CGPoint(x: 150, y: 150)
    }, completion: {
      _ in
      UIView.animate(withDuration: 2, animations: {
        // Rotate box 45 degrees
        box.transform = CGAffineTransform(rotationAngle: .pi/4)
        }, completion: .none)
  })

  UIView.animate(withDuration: 4, animations: { () -> Void in
    // Change background color to blue
    view.backgroundColor = UIColor.blue
  })
}

animationGroup.notify(queue: DispatchQueue.main) {
  print("Animations Completed!")
}

首先,引述:

通知(队列:工作:) 当一组以前提交的块对象完成时,计划将工作项提交到队列

基本上,没有“以前”提交的块,因此会立即调用
notify
块。发生这种情况是因为您在
DispatchQueue.main.async
中向组添加了工作项。您可以在调用
notify
方法之前,在
DispatchQueue.main.async(组:animationGroup)
中添加一个打印和另一个打印来检查这一点。第二个将首先打印

最重要的是,在
DispatchGroup.main.async
中调用异步函数是有问题的,因为工作项将立即进入,然后您将异步工作分派到另一个线程,即使异步工作没有完成,工作项也会立即离开

要解决此问题,必须在启动异步操作时调用
animationGroup.enter()
,然后在完成后调用
animationGroup.leave()
。此外,您必须将代码从
DispatchGroup.main.async
中取出。如果您进行了这些更改,则当
进入/离开
调用平衡时,将执行
通知
块。

在执行本身是同步的任务时,将使用您正在使用的API调用。例如,假设您打算在一些缓慢的同步API中处理一组图像,但希望在后台线程上并行运行,以避免阻塞主线程。然后使用
async(组:execute:)
API:

let group = DispatchGroup()
for image in images {
    DispatchQueue.global().async(group: group) {
        self.process(image)
    }
}

group.notify(queue: .main) {
    // all done processing the images
}
但是,在这种情况下,基于块的
UIView
animation API调用异步运行。所以您不能使用这种
async(组:execute:)
模式。在启动每个异步进程之前,您必须手动
输入
,然后
留在各自的完成闭包中,一对一地匹配它们:

animationGroup.enter()

UIView.animate(withDuration: 1, animations: {
    box.center = CGPoint(x: 150, y: 150)                           // Move box to lower right corner
}, completion: { _ in
    UIView.animate(withDuration: 2, animations: {
        box.transform = CGAffineTransform(rotationAngle: .pi / 4)  // Rotate box 45 degrees
    }, completion: { _ in
        animationGroup.leave()
    })
})

animationGroup.enter()

UIView.animate(withDuration: 4, animations: {
    view.backgroundColor = .blue                                   // Change background color to blue
}, completion: { _ in
    animationGroup.leave()
})

animationGroup.notify(queue: .main) {
    print("Animations Completed!")
}