如何在Swift 3,4和5中编写dispatch_after GCD?

时间:2016-06-14 01:07:06

标签: ios swift swift4 grand-central-dispatch swift5

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

dispatch_after

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

13 个答案:

答案 0 :(得分:1035)

语法很简单:

xml

注意,将// to run something in 0.1 seconds DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // your code here } 添加为seconds的上述语法似乎是混淆的原因(特别是因为我们习惯于添加nsec)。 “将{秒添加为Double”语法有效,因为Doubledeadline,并且在幕后,有一个DispatchTime运算符将采用+并将这几秒钟添加到Double

DispatchTime

但是,如果您确实要向public func +(time: DispatchTime, seconds: Double) -> DispatchTime 添加整数msec,μs或nsec,您还可以向DispatchTime添加DispatchTimeInterval。这意味着你可以这样做:

DispatchTime

由于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

有人询问如何取消已发送的任务。为此,请使用public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime 。例如,这将启动一个将在五秒内触发的任务,或者如果视图控制器被解除并取消分配,则其DispatchWorkItem将取消该任务:

deinit

请注意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() { ... } } [weak self]捕获列表的使用。这对于避免强大的参考周期至关重要。另请注意,这不会取消抢先取消,而只是暂停启动任务(如果尚未启动)。但是如果它在遇到DispatchWorkItem调用时已经开始,则该块将完成执行(除非您手动检查块内的cancel())。

答案 1 :(得分:124)

Swift 4:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
   // Code
}

对于.seconds(Int)时间,也可以使用.microseconds(Int).nanoseconds(Int)

答案 2 :(得分:57)

如果你只想要延迟功能

Swift 4& 5

func delay(interval: TimeInterval, closure: @escaping () -> Void) {
     DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
          closure()
     }
}

您可以像以下一样使用它:

delay(interval: 1) { 
    print("Hi!")
}

答案 3 :(得分:16)

在Swift 3发布之后,还必须添加@escaping

func delay(_ delay: Double, closure: @escaping () -> ()) {
  DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
    closure()
  }
}

答案 4 :(得分:5)

Swift 4

您可以在DispatchQueue上创建扩展并添加在内部使用DispatchQueue asyncAfter函数的函数延迟

extension DispatchQueue {
   static func delay(_ delay: DispatchTimeInterval, closure: @escaping () -> ()) {
      DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: closure)
   }
}

并使用

DispatchQueue.delay(.milliseconds(10)) {
   print("task to be done")
}

答案 5 :(得分:5)

接受的答案略有不同。

Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + .milliseconds(500) + 
.microseconds(500) + .nanoseconds(1000)) {
                print("Delayed by 0.1 second + 500 milliseconds + 500 microseconds + 
                      1000 nanoseconds)")
 }

答案 6 :(得分:3)

致电DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)

我强烈建议使用Xcode工具转换为Swift 3(编辑>转换>转换为当前Swift语法)。它为我抓住了这个

答案 7 :(得分:2)

在Swift 4.1和Xcode 9.4.1中

简单的答案是...

//To call function after 5 seconds time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}

答案 8 :(得分:1)

以上提到的答案均未在非主线程上运行,因此加2美分。

主队列(主线程)上

let mainQueue = DispatchQueue.main
let deadline = DispatchTime.now() + .seconds(10)
mainQueue.asyncAfter(deadline: deadline) {
    // ...
}

OR

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) { 
    // ...
}

全局队列上(非主线程,基于指定的QOS)。

let backgroundQueue = DispatchQueue.global()
let deadline = DispatchTime.now() + .milliseconds(100)
backgroundQueue.asyncAfter(deadline: deadline, qos: .background) { 
    // ...
}

OR

DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + .milliseconds(100), qos: .background) {
    // ...
}

答案 9 :(得分:1)

Swift 5及以上

DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
   // code to execute                 
})

答案 10 :(得分:0)

这在Swift 3中对我有用

let time1 = 8.23
let time2 = 3.42

// Delay 2 seconds


DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    print("Sum of times: \(time1 + time2)")
}

答案 11 :(得分:0)

您可以使用

DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(100)) {
        // Code
    }

答案 12 :(得分:0)

试试这个

let when = DispatchTime.now() + 1.5
    DispatchQueue.main.asyncAfter(deadline: when) {
        //some code
    }