dispatch_after en Swift : GCD sous le capot — analyse avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

dispatch_after en Swift : comment GCD exécute les tâches différées sous le capot



Imaginez : vous écrivez une application en Swift et vous devez exécuter un morceau de code non pas immédiatement, mais, disons, dans 3 secondes. La première chose qui vient à l'esprit est dispatch_after. Mais si vous regardez les anciennes versions de Swift ou Stack Overflow, vous verrez que cette méthode a changé. Et surtout, peu de gens comprennent ce qui se passe réellement à l'intérieur de Grand Central Dispatch (GCD) lorsque nous disons : « Fais ça dans 2 secondes ».



Dans cet article, nous ne montrerons pas seulement comment écrire dispatch_after en Swift moderne. Nous allons plonger sous le capot de GCD, analyser les files d'attente, les threads et les minuteurs, afin que vous puissiez écrire un code asynchrone fiable et efficace. C'est parti !



Qu'est-ce que dispatch_after et pourquoi est-il devenu asyncAfter ?



Dans les anciennes versions de Swift (1.x, 2.x), vous pouviez rencontrer ce code :



dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2 * NSEC_PER_SEC)), dispatch_get_main_queue()) {    print("2 secondes se sont écoulées")}


Ce code fonctionnait, mais paraissait lourd. À partir de Swift 3, Apple a refactorisé toute l'API GCD, la rendant plus « swifty ». Maintenant, la même fonctionnalité ressemble à ceci :



DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {    print("2 secondes se sont écoulées")}


Notez que asyncAfter est une méthode de file d'attente (DispatchQueue), et non une fonction séparée. C'est un changement clé : vous spécifiez maintenant explicitement sur quelle file d'attente exécuter la tâche.



Comment GCD fonctionne sous le capot : files d'attente, threads et minuteurs



Pour comprendre dispatch_after (ou asyncAfter), il faut comprendre trois entités :



  • DispatchQueue — la file d'attente des tâches. Elle peut être séquentielle (serial) ou parallèle (concurrent).
  • DispatchWorkItem — la tâche que vous placez dans la file d'attente. Dans notre cas, il s'agit d'une closure.
  • DispatchTime — le moment où la tâche doit démarrer. GCD utilise un minuteur système pour suivre les échéances.


Lorsque vous appelez asyncAfter, GCD ne crée pas un nouveau thread. Au lieu de cela, il :



  1. Crée un minuteur qui se déclenchera à l'heure spécifiée.
  2. Place la tâche dans une file d'attente spéciale pour les tâches différées (souvent appelée dispatch timer).
  3. Lorsque le minuteur se déclenche, GCD déplace la tâche vers la file d'attente normale DispatchQueue, où elle attend son thread.


Si la file d'attente dans laquelle vous placez la tâche est occupée par d'autres tâches, votre tâche différée peut s'exécuter après l'échéance spécifiée. C'est un point important : dispatch_after garantit que la tâche ne s'exécutera pas avant l'échéance, mais peut s'exécuter plus tard.



Exemple pratique : dispatch_after pour la mise à jour de l'interface utilisateur



Le scénario le plus courant est la mise à jour de l'interface après un certain temps suite à une action de l'utilisateur. Supposons que vous affichiez un message « Enregistré », puis que vous le retiriez après 2 secondes :



func showTemporaryMessage() {    let messageLabel = UILabel()    messageLabel.text = "Enregistré !"    messageLabel.alpha = 1.0    view.addSubview(messageLabel)

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { UIView.animate(withDuration: 0.5) { messageLabel.alpha = 0.0 } completion: { _ in messageLabel.removeFromSuperview() } }}


Notez que nous utilisons DispatchQueue.main, car toutes les opérations sur l'interface utilisateur doivent être effectuées sur le thread principal. Si nous avions appelé asyncAfter sur une file d'attente en arrière-plan, puis tenté de modifier l'interface, l'application aurait planté.



Pièges de dispatch_after : fuites mémoire et capture de self



L'une des erreurs les plus fréquentes est une référence forte à self à l'intérieur

Blogs

Book Recommendations