Comment programmer un retard dans Swift 3

330

Dans les versions antérieures de Swift, on pouvait créer un retard avec le code suivant:

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
}

Mais maintenant, dans Swift 3, Xcode change automatiquement 6 choses différentes mais l'erreur suivante apparaît: "Impossible de convertir DispatchTime.nowà la valeur attendue dispatch_time_taka UInt64."

Comment créer un délai avant d'exécuter une séquence de code dans Swift 3?

chouette
la source

Réponses:

967

Après beaucoup de recherches, j'ai finalement trouvé celui-ci.

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

Cela crée l'effet "d'attente" souhaité dans Swift 3 et Swift 4.

Inspiré d'une partie de cette réponse .

chouette
la source
7
Contribution utile, merci! Mise à jour pour le dernier Swift 3:DispatchQueue.main.asyncAfter(deadline: when)
Rogare
77
Vous pourriez rendre votre code un peu plus rapide en remplaçant "+ 2" par "+ .secondes (2)". Ou, pour le summum de la rapidité, vous pouvez supprimer la première ligne et remplacer "date limite: quand" par "date limite: .now () + .secondes (2)".
RenniePet
2
@ OctavioAntonioCedeño Heureux de vous aider. Cela m'a vraiment dérangé pendant un certain temps: D
owlswipe
5
Fonctionne toujours 3/12/2017. Merci beaucoup pour cela :)
John Leonardo
3
Littéralement mon article le plus visité sur SO. Il est plus facile de trouver ce message que de s'en souvenir ou de le trouver ailleurs dans mon code;)
barrylachapelle
154

J'aime la notation sur une ligne pour GCD, c'est plus élégant:

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

De plus, dans iOS 10, nous avons de nouvelles méthodes de temporisation, par exemple l'initialisation de bloc:

(l'action retardée peut donc être annulée)

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

Btw, gardez à l'esprit: par défaut, la minuterie est ajoutée au mode de boucle d'exécution par défaut. Cela signifie que le minuteur peut être gelé lorsque l'utilisateur interagit avec l'interface utilisateur de votre application (par exemple, lors du défilement d'un UIScrollView). Vous pouvez résoudre ce problème en ajoutant le minuteur au mode de boucle d'exécution spécifique:

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

À cet article de blog, vous pouvez trouver plus de détails.

Victor Do
la source
4
Bonne prise! Je n'avais pas encore vu ça.
julien_c
8
plus un pour la comparaison du minuteur et l'avertissement concernant le runloop principal!
Martin
2
Belle prise! C'est de l'ingénierie.
Onur Şahindur
56

Essayez la fonction suivante implémentée dans Swift 3.0 et supérieur

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

Usage

delayWithSeconds(1) {
   //Do something
}
Vakas
la source
5
Vous avez simplement copié cette réponse, mais oui, c'est bien, merci.
owlswipe
2
Comment annuler cela?
Sourav Chandra
24

Essayez le code ci-dessous pour le retard

//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
la source
1
Les affichages de la première manière comportent l'erreur "Utilisation d'un identifiant non résolu" retard ""
Jerry Chong
5
Ce programmeur travaille avec une méthode d'aide dans sa base de code et l'a depuis longtemps. Le retard était donc un code qu'il utilisait depuis un certain temps sans savoir qu'il ne faisait pas partie du SDK d'Apple.
Nick Perkins
4

Une façon consiste à utiliser DispatchQueue.main.asyncAftercomme beaucoup de gens ont répondu.

Une autre façon est d'utiliser perform(_:with:afterDelay:). Plus de détails ici

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

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

// Exécute la fonction après x secondes

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)
}

//Utilisation:-

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