So programmieren Sie eine Verzögerung in Swift 3

329

In früheren Versionen von Swift konnte eine Verzögerung mit dem folgenden Code erzeugt werden:

let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 4 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
    //put your code which should be executed with a delay here
}

Aber jetzt, in Swift 3, ändert Xcode automatisch 6 verschiedene Dinge, aber dann erscheint der folgende Fehler: "Kann nicht DispatchTime.nowin den erwarteten Wert dispatch_time_taka konvertieren UInt64."

Wie kann man eine Verzögerung erzeugen, bevor eine Codesequenz in Swift 3 ausgeführt wird?

Eulenwischen
quelle

Antworten:

964

Nach vielen Recherchen habe ich es endlich herausgefunden.

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Change `2.0` to the desired number of seconds.
   // Code you want to be delayed
}

Dies erzeugt den gewünschten "Warte" -Effekt in Swift 3 und Swift 4.

Inspiriert von einem Teil dieser Antwort .

Eulenwischen
quelle
7
Nützlicher Beitrag, danke! Aktualisierung für die neueste Swift 3:DispatchQueue.main.asyncAfter(deadline: when)
Rogare
77
Sie können Ihren Code etwas schneller gestalten, indem Sie "+ 2" durch "+ .seconds (2)" ersetzen. Oder für ein Höchstmaß an Schnelligkeit können Sie die erste Zeile löschen und "Deadline: When" durch "Deadline: .now () + .seconds (2)" ersetzen.
RenniePet
2
@ OctavioAntonioCedeño Gerne helfen wir Ihnen weiter. Das nervte mich wirklich für eine Weile: D
owlswipe
5
Arbeitet noch am 12.03.2017. Vielen Dank dafür :)
John Leonardo
3
Buchstäblich mein meistbesuchter Beitrag auf SO. Es ist einfacher, diesen Beitrag zu finden, als ihn tatsächlich zu merken oder an anderer Stelle in meinem Code zu finden;)
Barrylachapelle
154

Ich mag einzeilige Notation für GCD, es ist eleganter:

    DispatchQueue.main.asyncAfter(deadline: .now() + 42.0) {
        // do stuff 42 seconds later
    }

Außerdem haben wir in iOS 10 neue Timer-Methoden, z. B. Blockinitialisierer:

(so kann verzögerte Aktion abgebrochen werden)

    let timer = Timer.scheduledTimer(withTimeInterval: 42.0, repeats: false) { (timer) in
        // do stuff 42 seconds later
    }

Übrigens, denken Sie daran: Standardmäßig wird der Timer zum Standard-Run-Loop-Modus hinzugefügt. Dies bedeutet, dass der Timer möglicherweise eingefroren ist, wenn der Benutzer mit der Benutzeroberfläche Ihrer App interagiert (z. B. beim Scrollen einer UIScrollView). Sie können dieses Problem lösen, indem Sie den Timer dem spezifischen Run-Loop-Modus hinzufügen:

RunLoop.current.add(timer, forMode: .common)

In diesem Blogbeitrag finden Sie weitere Details.

Victor Do.
quelle
4
Guter Fang! Ich hatte das noch nicht gesehen.
julien_c
8
plus eins für den Timer-Vergleich und den Haftungsausschluss zum Haupt-Runloop!
Martin
2
Schöner Fang! Das ist Engineering.
Onur Şahindur
56

Probieren Sie die folgende in Swift 3.0 und höher implementierte Funktion aus

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

Verwendungszweck

delayWithSeconds(1) {
   //Do something
}
Vakas
quelle
5
Sie haben diese Antwort im Grunde nur kopiert , aber ja, das ist gut, danke.
Owlswipe
2
Wie kann ich das abbrechen?
Sourav Chandra
24

Versuchen Sie den folgenden Code für die Verzögerung

//MARK: First Way

func delayForWork() {
    delay(3.0) {
        print("delay for 3.0 second")
    }
}

delayForWork()

// MARK: Second Way

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    // your code here delayed by 0.5 seconds
}
Anand Verma
quelle
1
First Way Displays haben den Fehler "Verwendung der ungelösten Kennung 'Verzögerung'"
Jerry Chong
5
Dieser Programmierer arbeitet mit einer Hilfsmethode in seiner Codebasis und hat eine lange Zeit. Verzögerung war also Code, den er seit einiger Zeit verwendet hat, ohne zu wissen, dass er nicht zu Apples SDK gehört.
Nick Perkins
4

Eine Möglichkeit besteht darin, zu verwenden, DispatchQueue.main.asyncAfterwie viele Leute geantwortet haben.

Ein anderer Weg ist zu verwenden perform(_:with:afterDelay:). Weitere Details hier

perform(#selector(delayedFunc), with: nil, afterDelay: 3)

@IBAction func delayedFunc() {
    // implement code
}
Zohaib Brohi
quelle
1

// Führt die Funktion nach x Sekunden aus

public static func runThisAfterDelay(seconds: Double, after: @escaping () -> Void) {
    runThisAfterDelay(seconds: seconds, queue: DispatchQueue.main, after: after)
}

public static func runThisAfterDelay(seconds: Double, queue: DispatchQueue, after: @escaping () -> Void) {
    let time = DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
    queue.asyncAfter(deadline: time, execute: after)
}

//Verwenden:-

runThisAfterDelay(seconds: x){
  //write your code here
}
Pratyush Pratik
quelle