停止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理后台任务,你应该使用Operation
和OperationQueue
简单的例子:
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订单优化问题。