ProgrammationDéveloppeur Swift

Qu'est-ce que 'defer' en Swift ? Comment cela fonctionne-t-il et pourquoi l'utilise-t-on, quelles sont les utilisations non standard ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

L'opérateur defer retarde l'exécution du code jusqu'à la sortie de l'étendue de portée actuelle, généralement d'une fonction. Il est pratique pour nettoyer des ressources, fermer des fichiers et libérer de la mémoire – ce qu'on appelle un nettoyage automatisé.

Caractéristiques :

  • Les blocs defer s'exécutent dans l'ordre inverse de leur déclaration (LIFO).
  • L'appel se produit toujours — tant lors d'une sortie normale de la fonction que lors du déclenchement d'une erreur.
  • Permet d'éviter la duplication du code de nettoyage et maintient une architecture de fonctions propre.

Exemple :

func processFile() { let file = openFile() defer { closeFile(file) } // Travail avec le fichier // le fichier sera fermé même en cas de throw ou return }

Utilisation atypique : imitation partielle de constructions de type 'finally', regroupement de code pour la journalisation et le suivi des temps d'exécution.

Question piège.

Le defer s'exécutera-t-il si l'application se termine pendant l'exécution de la fonction ?

— Non. Le defer s'exécute uniquement lors de l'achèvement normal de l'étendue de portée (return, throw ou sortie normale). Si l'application se termine de manière inattendue (par exemple, en raison d'un signal SIGKILL ou d'une erreur fatale), les blocs defer n'auront pas le temps de s'exécuter.

Exemple :

func foo() { defer { print("Nettoyer") } fatalError("Crash !") // defer ne s'exécutera pas }

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet.


Histoire

Une fonction travaillant avec des sockets ne nettoyait pas la connexion en cas de throw. Les données restaient suspendues, les connexions n'étaient pas libérées. Après l'introduction de defer, tout fonctionnait correctement : les ressources se fermaient toujours.


Histoire

Un développeur tentait de s'appuyer sur defer pour libérer un état global. Lorsqu'un fatalError survenait, la ressource n'était pas libérée, ce qui entraînait des blocages des services et nécessitait un redémarrage.


Histoire

Dans une fonction, plusieurs defer étaient déclarés, pensant qu'ils s'exécuteraient dans l'ordre de déclaration. En conséquence, les ressources se fermaient dans le mauvais ordre (par exemple, le descripteur de fichier était fermé en premier, puis on essayait d'y accéder). Solution : se rappeler de l'ordre LIFO d'exécution des blocs defer.