如何在 Swift 3、4 和 5 中编写 dispatch_after GCD? [英] How do I write dispatch_after GCD in Swift 3, 4, and 5?

查看:23
本文介绍了如何在 Swift 3、4 和 5 中编写 dispatch_after GCD?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Swift 2 中,我能够使用 dispatch_after 使用大中央调度来延迟操作:

In Swift 2, I was able to use dispatch_after to delay an action using grand central dispatch:

var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))) 
dispatch_after(dispatchTime, dispatch_get_main_queue(), { 
    // your function here 
})

但这似乎从 Swift 3 开始就不再编译了.在现代 Swift 中编写它的首选方法是什么?

But this no longer seems to compile since Swift 3. What is the preferred way to write this in modern Swift?

推荐答案

语法很简单:

// to run something in 0.1 seconds

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    // your code here
}

<小时>

注意,将 seconds 添加为 Double 的上述语法似乎是一个混乱的来源(尤其是因为我们习惯于添加 nsec)."add seconds as Double" 语法是有效的,因为 deadline 是一个 DispatchTime 并且在幕后有一个 + 运算符,它将采用 Double 并将该秒数添加到 DispatchTime:


Note, the above syntax of adding seconds as a Double seems to be a source of confusion (esp since we were accustomed to adding nsec). That "add seconds as Double" syntax works because deadline is a DispatchTime and, behind the scenes, there is a + operator that will take a Double and add that many seconds to the DispatchTime:

public func +(time: DispatchTime, seconds: Double) -> DispatchTime

但是,如果你真的想给 DispatchTime 添加一个整数 msec、μs 或 nsec,你也可以添加一个 DispatchTimeInterval调度时间.这意味着你可以这样做:

But, if you really want to add an integer number of msec, μs, or nsec to the DispatchTime, you can also add a DispatchTimeInterval to a DispatchTime. That means you can do:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
    os_log("500 msec seconds later")
}

DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(1_000_000)) {
    os_log("1m μs seconds later")
}

DispatchQueue.main.asyncAfter(deadline: .now() + .nanoseconds(1_500_000_000)) {
    os_log("1.5b nsec seconds later")
}

由于 DispatchTime 类中的 + 运算符的这种单独的重载方法,所有这些都可以无缝地工作.

These all seamlessly work because of this separate overload method for the + operator in the DispatchTime class.

public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime

<小时>

有人问如何取消已调度的任务.为此,请使用 DispatchWorkItem.例如,这会启动一个将在 5 秒内触发的任务,或者如果视图控制器被解除并释放,它的 deinit 将取消任务:


It was asked how one goes about canceling a dispatched task. To do this, use DispatchWorkItem. For example, this starts a task that will fire in five seconds, or if the view controller is dismissed and deallocated, its deinit will cancel the task:

class ViewController: UIViewController {

    private var item: DispatchWorkItem?

    override func viewDidLoad() {
        super.viewDidLoad()

        item = DispatchWorkItem { [weak self] in
            self?.doSomething()
            self?.item = nil
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: item!)
    }

    deinit {
        item?.cancel()
    }

    func doSomething() { ... }

}

注意DispatchWorkItem[weak self] 捕获列表的使用.这对于避免强引用循环至关重要.另请注意,这不会进行抢占式取消,而只是在任务尚未启动时停止该任务.但是,如果它在遇到 cancel() 调用时已经启动,则该块将完成其执行(除非您手动检查该块内的 isCancelled).

Note the use of the [weak self] capture list in the DispatchWorkItem. This is essential to avoid a strong reference cycle. Also note that this does not do a preemptive cancelation, but rather just stops the task from starting if it hasn’t already. But if it has already started by the time it encounters the cancel() call, the block will finish its execution (unless you’re manually checking isCancelled inside the block).

这篇关于如何在 Swift 3、4 和 5 中编写 dispatch_after GCD?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆