ios - serial - swift gcd barrier




如何在Swift 3、4和5中編寫GCD中的dispatch_after? (9)

嘗試這個

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

在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中編寫此代碼的首選方法是什麼?


在Swift 3發布之後,還必須添加@escaping

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

如果您只想要延遲功能

斯威夫特4&5

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

您可以像這樣使用它:

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

您可以使用

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

沒有一個答案提到在非主線程上運行,因此加了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) {
    // ...
}

語法很簡單:

// to run something in 0.1 seconds

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

請注意,以上將 seconds 添加為 Double 語法似乎令人感到困惑(特別是因為我們習慣於添加nsec)。 之所以可以使用“將秒數 DoubleDouble ”語法,是因為 deadlineDispatchTime 並且在幕後有一個 + 運算符,它將佔用 Double 並將那麼多秒數加到 DispatchTime

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

但是,如果您確實想向 DispatchTime 添加整數毫秒,μs或nsec,則還可以向 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() { ... }

}

請注意 DispatchWorkItem [weak self] 捕獲列表的使用。 這對於避免強大的參考週期至關重要。 還要注意,這不會先發製人地取消,而是只是在任務尚未啟動時將其停止。 但是,如果它在遇到 cancel() 調用時已經啟動,則該塊將完成其執行(除非您在該塊中手動檢查 isCancelled )。


這在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)")
}

Swift 5及以上

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

斯威夫特4:

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

對於時間 .seconds(Int) ,也可以使用 .microseconds(Int).nanoseconds(Int)





swift5