ProgrammationDéveloppeur iOS/Swift

Qu'est-ce que les déclarations defer en Swift ? Quelles sont les particularités de son exécution, où est-il judicieux de l'appliquer et quels pièges peut-on rencontrer ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question :

Defer a été ajouté à Swift (inspiré par des analogues en Go, C#) pour un nettoyage garanti des ressources même en cas d'erreurs, de sortie de la fonction ou de retour de valeurs depuis différents points de fonctions.

Problème :

Libération prématurée, nettoyages de ressources oubliés (par exemple, fermeture de fichiers, journalisation, rollback de transactions). On confond parfois l'ordre d'exécution, pensant à tort que defer s'exécute au moment de la déclaration.

Solution :

Defer est un bloc spécial qui retarde l'exécution du code jusqu'à la fin de la portée actuelle (scope), généralement la fonction. Tous les defer s'exécutent dans l'ordre inverse de leur déclaration (LIFO). Cela permet de gérer de manière centralisée le nettoyage des ressources, la libération de mémoire ou le rollback de transactions.

Exemple de code :

func processFile() { let file = File("/tmp/data.txt") file.open() defer { file.close() print("Fichier fermé") } // Traitement du fichier print("Lecture des données…") }

Caractéristiques clés :

  • S'exécute toujours à la sortie de la portée, même en cas d'erreurs et de retour anticipé.
  • Plusieurs defer s'exécutent dans l'ordre inverse.
  • Peut être utilisé dans n'importe quelle portée, pas seulement dans les fonctions.

Questions pièges.

Le code à l'intérieur de defer s'exécute-t-il en cas de plantage de l'application (crash) avant la sortie de la fonction ?

Non, le code defer s'exécute uniquement lors d'une sortie correcte de la portée (scope). Si l'application se termine par une erreur fatale (par exemple, fatal error), le defer ne sera pas exécuté.

Peut-on utiliser return à l'intérieur de defer ?

Non, ce n'est pas possible. Le bloc defer ne permet pas de retourner des valeurs ou de terminer la portée, seulement des instructions.

Le defer peut-il être utilisé pour modifier des variables déclarées avant le defer ?

Oui, defer capture les valeurs de la pile actuelle au moment de son exécution. Il est possible de modifier les valeurs déclarées avant defer, et elles seront conservées à la sortie de la portée.

Exemple de code :

func example() -> Int { var result = 0 defer { result = 42 } return result // defer s'exécutera, le résultat — 42 }

Erreurs typiques et anti-patterns

  • Attente erronée de l'exécution de defer immédiatement après sa déclaration.
  • Utilisation de defer en dehors de la portée, où cela n'a pas de sens.
  • Laisser des opérations lourdes à l'intérieur de defer.

Exemple de la vie réelle

Cas négatif

Le fichier est ouvert, mais se ferme seulement explicitement à la fin de la fonction, et en cas d'erreurs ou de sortie anticipée, le fichier reste ouvert.

Avantages :

  • Simplicité de mise en œuvre

Inconvénients :

  • Le fichier ne se ferme pas en cas d'erreurs
  • Fuite de ressources

Cas positif

Utilisation de defer pour fermer le fichier immédiatement après son ouverture. Même en cas d'exception ou de retour de la fonction, le fichier se fermera de manière garantie.

Avantages :

  • Sûr, pas de fuites
  • Code propre et prévisible

Inconvénients :

  • Nécessité de faire attention aux ressources mutables à l'intérieur de defer