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

ios swift swift4 grand-central-dispatch swift5

189775 观看

13回复

39936 作者的声誉

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

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中编写它的首选方法是什么?

作者: brandonscript 的来源 发布者: 2016 年 6 月 14 日

回应 (13)


3

2468 作者的声誉

呼叫 DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)

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

作者: jjatie 发布者: 14.06.2016 01:12

1057

316239 作者的声誉

决定

语法很简单:

// to run something in 0.1 seconds

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

请注意,增加的上述语法seconds作为Double似乎是混乱(ESP因为我们已经习惯了将纳秒)的来源。“添加秒作为Double”语法是有效的,因为它deadline是一个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()调用时已经开始,则块将完成其执行(除非您在isCancelled块内手动检查)。

作者: Rob 发布者: 14.06.2016 01:31

125

15050 作者的声誉

斯威夫特4:

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

对于时间.seconds(Int).microseconds(Int)并且.nanoseconds(Int)也可使用。

作者: Hannes Sverrisson 发布者: 17.06.2016 10:27

57

5300 作者的声誉

如果您只想要延迟功能

斯威夫特4和5

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

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

delay(interval: 1) { 
    print("Hi!")
}
作者: rockdaswift 发布者: 29.07.2016 07:09

16

825 作者的声誉

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

func delay(_ delay: Double, closure: @escaping () -> ()) {
  DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
    closure()
  }
}
作者: Marco Pappalardo 发布者: 03.10.2016 03:40

0

1477 作者的声誉

这在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)")
}
作者: Ankit garg 发布者: 30.03.2017 10:48

5

7613 作者的声誉

斯威夫特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")
}
作者: Suhit Patil 发布者: 24.06.2017 04:06

0

401 作者的声誉

您可以使用

DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(100)) {
        // Code
    }
作者: Parth Dhorda 发布者: 26.07.2017 11:29

5

3797 作者的声誉

接受的答案有点不同的味道。

斯威夫特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)")
 }
作者: Md. Ibrahim Hassan 发布者: 07.11.2017 06:53

0

6 作者的声誉

试试这个

let when = DispatchTime.now() + 1.5
    DispatchQueue.main.asyncAfter(deadline: when) {
        //some code
    }
作者: A.Guz 发布者: 07.11.2017 12:58

2

4277 作者的声誉

在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
}
作者: iOS 发布者: 18.08.2018 06:11

1

1916 作者的声誉

没有提到在非主线程上运行的答案,所以加上我的2美分。

主队列(主线程)

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

要么

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) { 
    // ...
}

要么

DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + .milliseconds(100), qos: .background) {
    // ...
}
作者: MANN 发布者: 18.02.2019 09:41

1

407 作者的声誉

斯威夫特5及以上

DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
   // code to execute                 
})
作者: midhun p 发布者: 24.04.2019 12:07
32x32