Update: Aus dem Swift 2.2-Änderungsprotokoll (veröffentlicht am 21. März 2016):
Bestimmte Klasseninitialisierer, die als fehlerhaft oder auslösend deklariert wurden, können jetzt null zurückgeben oder einen Fehler auslösen, bevor das Objekt vollständig initialisiert wurde.
Für Swift 2.1 und früher:
Gemäß der Dokumentation von Apple (und Ihrem Compilerfehler) muss eine Klasse alle gespeicherten Eigenschaften initialisieren, bevor sie nil
von einem fehlgeschlagenen Initialisierer zurückkehrt:
Bei Klassen kann ein fehlgeschlagener Initialisierer jedoch erst dann einen Initialisierungsfehler auslösen, wenn alle von dieser Klasse eingeführten gespeicherten Eigenschaften auf einen Anfangswert gesetzt wurden und eine Initialisierungsdelegierung stattgefunden hat.
Hinweis: Es funktioniert tatsächlich gut für Strukturen und Aufzählungen, nur nicht für Klassen.
Die vorgeschlagene Methode zum Behandeln gespeicherter Eigenschaften, die nicht initialisiert werden können, bevor der Initialisierer fehlschlägt, besteht darin, sie als implizit entpackte Optionen zu deklarieren.
Beispiel aus den Dokumenten:
class Product {
let name: String!
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
Im obigen Beispiel ist die Eigenschaft name der Produktklasse so definiert, dass sie einen implizit entpackten optionalen Zeichenfolgentyp (String!) Hat. Da es sich um einen optionalen Typ handelt, bedeutet dies, dass die Eigenschaft name den Standardwert nil hat, bevor ihr während der Initialisierung ein bestimmter Wert zugewiesen wird. Dieser Standardwert von nil bedeutet wiederum, dass alle von der Produktklasse eingeführten Eigenschaften einen gültigen Anfangswert haben. Infolgedessen kann der fehlgeschlagene Initialisierer für Product zu Beginn des Initialisierers einen Initialisierungsfehler auslösen, wenn ihm eine leere Zeichenfolge übergeben wird, bevor der Eigenschaft name im Initialisierer ein bestimmter Wert zugewiesen wird.
In Ihrem Fall wird der Kompilierungsfehler jedoch nicht durch einfaches Definieren userName
als String!
behoben, da Sie sich weiterhin um die Initialisierung der Eigenschaften Ihrer Basisklasse kümmern müssen NSObject
. Glücklicherweise können Sie mit userName
definiert als a String!
tatsächlich super.init()
vor Ihnen aufrufen , return nil
wodurch Ihre NSObject
Basisklasse initiiert und der Kompilierungsfehler behoben wird.
class User: NSObject {
let userName: String!
let isSuperUser: Bool = false
let someDetails: [String]?
init?(dictionary: NSDictionary) {
super.init()
if let value = dictionary["user_name"] as? String {
self.userName = value
}
else {
return nil
}
if let value: Bool = dictionary["super_user"] as? Bool {
self.isSuperUser = value
}
self.someDetails = dictionary["some_details"] as? Array
}
}
canSetCalculableProperties
booleschen Parameter hinzugefügt , mit dem mein Initialisierer Eigenschaften berechnen kann, die im laufenden Betrieb erstellt werden können oder nicht. Wenn beispielsweise eindateCreated
Schlüssel fehlt und ich die EigenschaftcanSetCalculableProperties
im laufenden Betrieb festlegen kann, weil der Parameter true ist, setze ich ihn einfach auf das aktuelle Datum.