Składnia jest po prostu:
// to run something in 0.1 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// your code here
}
Zauważ, że powyższa składnia dodawania secondsjako a Doublewydaje się być źródłem nieporozumień (szczególnie, że byliśmy przyzwyczajeni do dodawania nsec). Ta Doubleskładnia „dodaj sekundy jako ” działa, ponieważ deadlinejest DispatchTimea, za kulisami istnieje +operator, który zajmie Doublei doda tyle sekund do DispatchTime:
public func +(time: DispatchTime, seconds: Double) -> DispatchTime
Ale jeśli naprawdę chcesz dodać liczbę całkowitą msec, μs lub nsec do DispatchTime, możesz również dodać a DispatchTimeIntervaldo DispatchTime. Oznacza to, że możesz:
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")
}
Wszystko to działa bezproblemowo dzięki oddzielnej metodzie przeciążenia dla +operatora w DispatchTimeklasie.
public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
Zapytano, jak można anulować wysłane zadanie. Aby to zrobić, użyj DispatchWorkItem. Na przykład uruchamia to zadanie, które zostanie uruchomione za pięć sekund, lub jeśli kontroler widoku zostanie zwolniony i cofnięty, deinitanuluje zadanie:
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() { ... }
}
Zwróć uwagę na użycie [weak self]listy przechwytywania w DispatchWorkItem. Jest to niezbędne, aby uniknąć silnego cyklu odniesienia. Zauważ również, że nie powoduje to zapobiegawczego anulowania, ale po prostu zatrzymuje uruchamianie zadania, jeśli jeszcze tego nie zrobiło. Ale jeśli już się zaczął, zanim napotka cancel()wywołanie, blok zakończy wykonywanie (chyba że ręcznie sprawdzasz isCancelledwewnątrz bloku).