Failable Initialisierer (init?) in Swift ermöglichen es, eine Situation zu beschreiben, in der die Erstellung einer Instanz eines Typs fehlschlagen kann und nil zurückgegeben wird. Sie werden häufig zur Validierung von Eingabedaten oder Transformationen verwendet, die möglicherweise nicht erfolgreich sind. In einem failable Initialisierer kann man explizit nil zurückgeben, um anzuzeigen, dass die Erstellung des Objekts gescheitert ist.
Beispiel:
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 } }
So kann man die Erstellung von ungültigen Objekten verhindern.
compactMap), ist dies praktisch zur Filterung ungültiger Instanzen.Frage: Was ist der Unterschied zwischen init? und init! und wann sollte man einen failable Initialisierer mit impliziter Entpackung verwenden?
Antwort: init? gibt ein Optional (<type?>) zurück, und wenn die Initialisierung fehlschlägt, wird nil zurückgegeben, was eine sichere Behandlung erfordert. init! gibt ein implicitly unwrapped optional (<type!>) zurück, und wenn die Initialisierung fehlschlägt, wird ebenfalls nil zurückgegeben, aber die Verwendung eines solchen Objekts ohne Prüfung führt zu einem Runtime-Crash. Verwenden Sie init! nur, wenn Sie sich sicher sind, dass die Initialisierung in Ihrem Kontext nicht fehlschlagen kann (zum Beispiel bei der Arbeit mit Storyboards in UIKit).
let value = Int("abc") // value wird nil sein
Geschichte
Beim manuellen Parsen von JSON wurde ein gewöhnlicher Initialisierer anstelle eines failable verwendet. Dies führte zur Erstellung "leerer" Benutzer, da die Validierung fehlte und die Anwendung ungültige Daten nicht filterte.
Geschichte
Die Verwendung von
init!mit potenziell ungültigen Daten führte zu einem Absturz der Anwendung nach einer API-Aktualisierung: Das Format der Eingabedaten hatte sich geändert, und bei der Entpackung des Objekts trat eine Laufzeitausnahme aufgrund der impliziten Entpackung von nil auf.
Geschichte
Bei einer benutzerdefinierten Implementierung von failable init wurde vergessen, nil explizit für bestimmte Szenarien zurückzugeben, und letztlich wurde die Struktur mit "schmutzigen" Feldern initialisiert, was später zu Bugs in der Geschäftslogik führte.