Wie man aufhört, Verzögerungen zu fürchten und GCD in Swift 3, 4 und 5 lieben lernt
\n\nHaben Sie jemals Code geschrieben, der nach drei Sekunden ausgeführt werden sollte, aber sofort ausgelöst wurde? Oder im Gegenteil, eine Ewigkeit gewartet, obwohl Sie nur ein paar Millisekunden eingeplant hatten? Kommt Ihnen bekannt vor? Dann sind Sie definitiv auf dispatch_after gestoßen – eines der beliebtesten, aber auch tückischsten Werkzeuge von Grand Central Dispatch (GCD).
\n\nFrüher, in der Ära von Swift 2 und Objective-C, sah diese Methode wie ein Zauberspruch aus: dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(nanoseconds)), dispatch_get_main_queue()). Aber mit dem Aufkommen von Swift 3, 4 und 5 wurde die GCD-API komplett neu geschrieben. Heute ist das nicht nur eine Namensänderung – es ist eine neue Denkweise. In diesem Artikel analysieren wir, wie man dispatch_after in Swift in allen aktuellen Versionen schreibt, räumen mit Mythen auf und liefern fertige Lösungen. Los geht's!
Was ist mit dispatch_after passiert? Eine kurze Geschichte des Schmerzes
\nVor Swift 3 verwendeten Entwickler GCD im C-Stil:
\nlet delay = dispatch_time(DISPATCH_TIME_NOW, Int64(2.0 * Double(NSEC_PER_SEC)))\ndispatch_after(delay, dispatch_get_main_queue()) {\n print("Hallo aus der Vergangenheit!")\n}\nDas funktionierte, sah aber umständlich aus. In Swift 3 beschloss Apple, GCD zu "swiften" und in eine objektorientierte API zu verwandeln. Jetzt wurde dispatch_after zur Methode asyncAfter der Struktur DispatchQueue. Und das ist nicht nur eine kosmetische Renovierung – es ist eine völlig neue Syntax, die Verständnis erfordert.
Das Grundrezept: asyncAfter in Swift 3, 4 und 5
\nUnabhängig von der Swift-Version (3, 4 oder 5) sieht die grundlegende Syntax von dispatch_after jetzt gleich aus. Hier ist das einfachste Beispiel für eine verzögerte Ausführung auf dem Hauptthread:
\n\nlet delayInSeconds: Double = 2.0\nDispatchQueue.main.asyncAfter(deadline: .now() + delayInSeconds) {\n print("2 Sekunden sind vergangen!")\n}\nWichtige Punkte:
\n- \n
- DispatchQueue.main – der Hauptthread (UI). \n
- .now() + delayInSeconds – erstellt einen Deadline (Frist) relativ zum aktuellen Zeitpunkt. \n
- asyncAfter – asynchrone Ausführung nach der angegebenen Zeit. \n
Dieser Code funktioniert in Swift 3.0, 4.0 und 5.0 ohne Änderungen. Die Magie liegt darin, dass Apple diese API seit 2016 stabil gelassen hat.
\n\nUnd was ist mit dispatch_time? Arbeiten mit Nanosekunden
\nManchmal müssen Sie eine Verzögerung in Nanosekunden angeben (z. B. für präzise Timer oder Spiellogik). In der neuen API wird DispatchTime verwendet:
\nlet nanoseconds: Int = 1_500_000_000 // 1,5 Sekunden\nlet deadline = DispatchTime.now() + .nanoseconds(nanoseconds)\nDispatchQueue.global().asyncAfter(deadline: deadline) {\n print("Nach 1,5 Sekunden im Hintergrundthread ausgeführt")\n}\nSie können auch vordefinierte Konstanten verwenden: .seconds(5), .milliseconds(500) und sogar .microseconds(1000). Das ist bequemer, als mit NSEC_PER_SEC zu multiplizieren.
Häufige Fragen (und Antworten!) zu dispatch_after in Swift
\nAuf Stack Overflow hat diese Frage Tausende von Aufrufen. Hier sind die häufigsten Fallstricke, auf die Anfänger treten.
\n\n1. Warum wird mein Code sofort ausgeführt und nicht mit Verzögerung?
\nDer häufigste Fehler ist die Verwechslung von asyncAfter mit async. Wenn Sie vergessen, deadline: anzugeben, oder DispatchQueue.main.async { ... } schreiben, wird der Code sofort ausgeführt. Der zweite Grund: Übergabe eines negativen Werts. .now() + (-5.0) ist eine vergangene Zeit, GCD führt den Block sofort aus.
2. Wie kann man dispatch_after abbrechen?
\nIm Gegensatz zu Timer hat asyncAfter keine eingebaute cancel()-Methode. Aber es gibt zwei Lösungen:
- \n
- Abbruch-Flag: Verwenden Sie ein
Dispatc