Aktualizacja: z dziennika zmian Swift 2.2 (opublikowanego 21 marca 2016 r.):
Wyznaczone inicjatory klas zadeklarowane jako dostępne lub zgłaszające mogą teraz zwracać odpowiednio nil lub zgłaszać błąd, zanim obiekt zostanie w pełni zainicjowany.
Dla Swift 2.1 i starszych:
Zgodnie z dokumentacją Apple (i błędem kompilatora), klasa musi zainicjować wszystkie swoje przechowywane właściwości przed powrotem nil
z dostępnego inicjatora:
Jednak w przypadku klas dostępny inicjator może wyzwolić błąd inicjalizacji tylko wtedy, gdy wszystkie przechowywane właściwości wprowadzone przez tę klasę zostały ustawione na wartość początkową i nastąpiło delegowanie inicjatora.
Uwaga: w rzeczywistości działa dobrze w przypadku struktur i wyliczeń, ale nie klas.
Sugerowanym sposobem obsługi przechowywanych właściwości, których nie można zainicjować przed niepowodzeniem inicjatora, jest zadeklarowanie ich jako niejawnie rozpakowanych opcji.
Przykład z dokumentów:
class Product {
let name: String!
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
W powyższym przykładzie właściwość name klasy Product jest zdefiniowana jako posiadająca niejawnie rozpakowany opcjonalny typ ciągu (String!). Ponieważ jest to typ opcjonalny, oznacza to, że właściwość name ma domyślną wartość nil, zanim zostanie przypisana określona wartość podczas inicjalizacji. Ta domyślna wartość zero z kolei oznacza, że wszystkie właściwości wprowadzone przez klasę Product mają prawidłową wartość początkową. W rezultacie dostępny inicjator dla produktu może wyzwolić błąd inicjalizacji na początku inicjatora, jeśli zostanie przekazany pusty ciąg, przed przypisaniem określonej wartości do właściwości name w inicjatorze.
W twoim przypadku, jednak po prostu definiując userName
jako String!
nie naprawić błąd kompilacji, ponieważ wciąż trzeba się martwić o inicjowanie właściwości na swojej klasy bazowej NSObject
. Na szczęście z userName
definicją a String!
, możesz zadzwonić super.init()
przed tobą, return nil
co zainicjuje twoją NSObject
klasę bazową i naprawi błąd kompilacji.
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
parametr boolowski, który umożliwia mojemu inicjatorowi obliczenie właściwości, które można lub nie można utworzyć w locie. Na przykład, jeślidateCreated
brakuje klucza i mogę ustawić właściwość w locie, ponieważcanSetCalculableProperties
parametr ma wartość true, po prostu ustawiam go na bieżącą datę.