Best practice zur Umsetzung einer failable Initialisierung in Swift
Mit dem folgenden code versuche ich zu definieren, die eine einfache model-Klasse und es ist failable-Initialisierer, die einen (json-) Wörterbuch als parameter auf. Die Initialisierung sollte zurück nil
wenn der user-name ist nicht definiert in der original-json.
1.
Warum nicht den code zu kompilieren? Die Fehlermeldung sagt:
Alle gespeicherten Eigenschaften einer Instanz der Klasse initialisiert werden müssen, vor der Rückgabe nil aus einem Initialisierer.
Das macht keinen Sinn. Warum sollte ich initialisieren die Eigenschaften, wenn ich Plane, zurück nil
?
2.
Ist mein Ansatz der richtige oder gibt es andere Ideen oder gemeinsame Muster zu erreichen mein Ziel?
class User: NSObject {
let userName: String
let isSuperUser: Bool = false
let someDetails: [String]?
init?(dictionary: NSDictionary) {
if let value: String = dictionary["user_name"] as? String {
userName = value
}
else {
return nil
}
if let value: Bool = dictionary["super_user"] as? Bool {
isSuperUser = value
}
someDetails = dictionary["some_details"] as? Array
super.init()
}
}
InformationsquelleAutor der Frage Kai Huppmann | 2014-10-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Update: Aus der Swift 2.2 Change-Log (veröffentlicht am März 21, 2016):
Für Swift 2.1 und früher:
Laut apples Dokumentation (und den compiler-Fehler), eine Klasse initialisieren muss, alle seine gespeicherten Einstellungen, die vor der Rückgabe
nil
aus einer failable Initialisierer:Hinweis: Es tatsächlich funktioniert gut für Strukturen und Enumerationen nicht nur in Klassen.
Die vorgeschlagene Weise zu behandeln gespeicherten Eigenschaften können nicht initialisiert werden, bevor die Initialisierung fehlschlägt, ist zu erklären, Sie als implizit unwrapped optionals.
Beispiel aus den docs:
In Ihrem Fall jedoch einfach die Definition
userName
alsString!
nicht fix die compile-Fehler, weil Sie noch brauchen, um über die Initialisierung der Eigenschaften Ihrer BasisklasseNSObject
. Zum Glück, mituserName
definiert als eineString!
können Sie tatsächlich rufensuper.init()
bevor Siereturn nil
die init IhreNSObject
Basisklasse und fix die compile-Fehler.InformationsquelleAutor der Antwort Mike S
Laut Chris Lattner dies ist ein bug. Hier ist, was er sagt:
Quelle
EDIT:
So swift ist jetzt open-source und gemäß dieses changelog es ist jetzt fest in Momentaufnahmen von swift 2.2
InformationsquelleAutor der Antwort mustafa
Ich akzeptiere, dass Mike 'S Antwort ist Apple' s Empfehlung, aber ich glaube nicht, dass es die beste Praxis. Der springende Punkt bei der ein starker Typ system ist, sich zu bewegen runtime-Fehlern, die zur compile-Zeit. Diese "Lösung" Niederlagen Zweck. IMHO besser wäre es, nach vorne zu gehen, und initialisieren Sie den Benutzernamen
""
und dann überprüfen Sie es nach der super.init(). Wenn leere Benutzernamen erlaubt sind, dann ein flag zu setzen.InformationsquelleAutor der Antwort Daniel T.
Andere Weise zum Zwecke der Umgehung der Begrenzung ist das arbeiten mit einer Klasse-Funktionen für die Initialisierung.
Sie wollen vielleicht sogar zu bewegen, die Funktion einer Erweiterung:
Verwenden würde:
InformationsquelleAutor der Antwort Kevin R
Obwohl Swift 2.2 freigegeben wurde, und Sie müssen nicht mehr vollständig initialisieren das Objekt, bevor er die Initialisierung, die Sie benötigen, um Ihre Pferde halten, bis https://bugs.swift.org/browse/SR-704 ist behoben.
InformationsquelleAutor der Antwort sssilver
Fand ich heraus, das kann getan werden in Swift 1.2
Gibt es einige Bedingungen:
Beispiel:
InformationsquelleAutor der Antwort Pim
Auszug Aus: Apple Inc. "Der Swift Programmiersprache." iBooks. https://itun.es/sg/jEUH0.l
InformationsquelleAutor der Antwort user1046037
Können Sie Bequemlichkeit init:
InformationsquelleAutor der Antwort Максим Петров