停止UIView中的所有asynchronous任务

我正在创build一个在UIViewController运行许多asynchronous任务的UIView 。 在某些时候,我希望能够移除UIView并停止所有正在运行的任务。 但是,调用removeFromSuperview()不会停止任务。 有没有办法可以做到这一点?

示例代码

 class ViewController: UIViewController { let v = SomeView() override func viewDidLoad() { super.viewDidLoad() v.frame = CGRect(x: 0, y: 0, width: 10, height: 10) self.view.addSubview(v) let v1 = UIButton() v1.frame = CGRect(x: 0, y: 0, width: 100, height: 100) v1.backgroundColor = UIColor.blue v1.addTarget(self, action: #selector(removeV(_:)), for: .touchUpInside) self.view.addSubview(v1) } func removeV(_ sender: UIButton) { print("V REMOVED") v.removeFromSuperview() } } class SomeView: UIView { override func draw(_ rect: CGRect) { DispatchQueue.global().async { var c = 0 while true { print(String(c) + " DOING SOME TASK") c += 1 sleep(1) } } } } 

示例日志

 0 DOING SOME TASK 1 DOING SOME TASK V REMOVED 2 DOING SOME TASK 3 DOING SOME TASK 4 DOING SOME TASK ... 

有一种方法可以使用DispatchWorkItem取消DispatchQueue中的块。 例如。

 //create the dispatch work item var dwi2:DispatchWorkItem? dwi2 = DispatchWorkItem { var c = 0 while true { print(String(c) + " DOING SOME TASK") c += 1 sleep(1) if (dwi2?.isCancelled)!{ break } } } //submit the work item to the default global queue DispatchQueue.global().async(execute: dwi2!) //cancelling the task after 3 seconds DispatchQueue.global().async{ sleep(3) dwi2?.cancel() } 

您将不得不检查工作块内的isCancelled属性以停止进一步的执行。

请参阅这个写得好的文章了解更多细节。

总之,你不能停止GCD任务。

要添加能力pipe理后台任务,你应该使用OperationOperationQueue简单的例子:

 class YourOperation: Operation { func execute() { // Execute your async task here. // call finish() if success finished tasks // call cancel() if some error } } let queue = OperationQueue() let yourOperation = YourOperation() queue.addOperation(yourOperation) // to stop single operation yourOperation.cancel() // to stop all operations queue.cancelAllOperations() 

您可以在您的SomeView实例中存储任务队列。 检查文档以获取更多信息。

提示:您可以根据需要添加尽可能多的操作,然后在删除时调用-cancelAllOperations

你不需要像其他人提到的那样,把自己的生活和国家统计局的工作相混淆。 你有可能持有一个标志(而不是while true – > while flag ),并将其设置为false,当你想要任务退出。 这样你也可以在任何时候退出,完全控制你的stream量和可能的错误。

另外,为了使事情更健壮,可以在该标志读取之前使用无锁内存屏障(因为您将从不同的线程读取/写入)。 这样你将避免CPUcaching和内存W / R订单优化问题。