ProgrammationDéveloppeur iOS

Comment fonctionnent les initialisateurs échoués (`init?`) en Swift ? Quand et pourquoi les utiliser, quels points importants doivent être pris en compte ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Les initialisateurs échoués (init?) en Swift permettent de décrire une situation où la création d'une instance d'un type peut échouer et renvoyer nil. Ils sont souvent utilisés pour valider les données d'entrée ou pour des transformations qui peuvent ne pas réussir. Dans un init échoué, on peut explicitement renvoyer nil, indiquant un échec dans la création de l'objet.

Exemple :

struct User { let name: String let age: Int init?(name: String, age: Int) { guard !name.isEmpty, age > 0 else { return nil } self.name = name self.age = age } }

Cela permet d'éviter la création d'objets incorrects.

Points importants :

  • Dans une chaîne d'héritage, les initialisateurs échoués ne peuvent être redéfinis que par des initialisateurs échoués.
  • Lors de l'utilisation d'une structure avec un initialisateur échoué dans un tableau, où il y a un mappage d'initialisation (compactMap), c'est pratique pour filtrer les instances non valides.

Question piégée

Question: Quelle est la différence entre init? et init! et quand utiliser un initialisateur échoué avec le déballage implicite ?

Réponse : init? renvoie un optionnel (<type?>), et si l'initialisation échoue, cela renverra nil, ce qui nécessite un traitement sécurisé. init! renvoie un optionnel déballé implicitement (<type!>), et si l'initialisation échoue, cela renverra également nil, mais l'utilisation de cet objet sans vérification entraînera un crash au moment de l'exécution. Utilisez init! uniquement si vous êtes certain que l'initialisation ne peut pas échouer dans votre contexte (par exemple, lors de l'utilisation d'un storyboard dans UIKit).

let value = Int("abc") // value sera nil

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet.


Histoire

Lors du parsing de JSON manuellement, un initialisateur normal a été utilisé au lieu d'un échoué. Cela a entraîné la création d'utilisateurs "vides", car la validation n'a pas fonctionné et l'application n'a pas filtré les données non valides.


Histoire

L'utilisation de init! avec des données potentiellement non valides a entraîné le crash de l'application après la mise à jour de l'API : le format des données d'entrée a changé, et au moment d'extraire l'objet, une exception d'exécution est survenue en raison du déballage implicite de nil.


Histoire

Lors de la réalisation d'un init échoué personnalisé, il a été oublié de renvoyer explicitement nil pour certains scénarios, et au final, la structure a été initialisée avec des champs "sales", ce qui a ensuite causé des bugs dans la logique métier.