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 seconds
jako a Double
wydaje się być źródłem nieporozumień (szczególnie, że byliśmy przyzwyczajeni do dodawania nsec). Ta Double
składnia „dodaj sekundy jako ” działa, ponieważ deadline
jest DispatchTime
a, za kulisami istnieje +
operator, który zajmie Double
i 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 DispatchTimeInterval
do 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 DispatchTime
klasie.
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, deinit
anuluje 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 isCancelled
wewnątrz bloku).