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

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

问题描述

在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).之所以可以使用将秒数添加为Double"的语法,是因为deadlineDispatchTime,并且在后台有一个+运算符,该运算符将使用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添加整数毫秒,μs或nsec,则还可以向DispatchTime添加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.例如,这将启动一个任务,该任务将在五秒钟内触发,或者如果视图控制器被解雇并释放,则其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中编写GCD中的dispatch_after?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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