停止UIView中的所有异步任务

时间:2017-08-07 10:57:56

标签: ios swift uiview

我正在创建UIView,在UIViewController内运行许多异步任务。在某些时候,我希望能够删除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
...

4 个答案:

答案 0 :(得分:5)

有一种方法可以使用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属性以停止进一步执行。

有关详细信息,请参阅this写得很好的帖子。

答案 1 :(得分:2)

简而言之,无法停止GCD任务。

要添加才能管理后台任务,您应该使用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()

答案 2 :(得分:0)

您可以在SomeView实例中存储包含任务的队列。查看documentation了解详情。

提示:您可以根据需要添加任意数量的操作,然后在删除时调用-cancelAllOperations

答案 3 :(得分:0)

你并不需要像其他人提到的那样使你的生活复杂化。您可以保留标记(而不是while true - > while flag),并在您希望任务退出时将其设置为false。通过这种方式,您也可以随时退出,并完美控制流量和可能的错误。

此外,为了使事情更加健壮,您可以在该标志读取之前使用无锁内存屏障(因为您将从不同的线程读取/写入它)。这样你就可以避免cpu缓存和内存w / r顺序优化问题。