Обновление: из журнала изменений Swift 2.2 (выпущено 21 марта 2016 г.):
Инициализаторы назначенных классов, объявленные как сбойные или вызывающие, теперь могут возвращать nil или вызывать ошибку, соответственно, до полной инициализации объекта.
Для Swift 2.1 и ранее:
Согласно документации Apple (и ошибке вашего компилятора), класс должен инициализировать все свои сохраненные свойства перед возвратом nil
из неудачного инициализатора:
Для классов, однако, отказавший инициализатор может вызвать сбой инициализации только после того, как все сохраненные свойства, введенные этим классом, были установлены на начальное значение и произошло любое делегирование инициализатора.
Примечание. На самом деле он отлично работает для структур и перечислений, но не для классов.
Предлагаемый способ обработки сохраненных свойств, которые не могут быть инициализированы до сбоя инициализатора, - объявить их как неявно развернутые необязательные параметры.
Пример из документов:
class Product {
let name: String!
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
В приведенном выше примере свойство name класса Product определяется как имеющее неявно развернутый необязательный строковый тип (String!). Поскольку это необязательный тип, это означает, что свойство name имеет значение по умолчанию nil, прежде чем ему будет присвоено конкретное значение во время инициализации. Это значение по умолчанию, равное nil, в свою очередь, означает, что все свойства, представленные классом Product, имеют допустимое начальное значение. В результате сбойный инициализатор для продукта может вызвать сбой инициализации в начале инициализатора, если ему передается пустая строка, перед присвоением определенного значения свойству name в инициализаторе.
В вашем случае, однако, простое определение userName
как a String!
не устраняет ошибку компиляции, потому что вам все еще нужно беспокоиться об инициализации свойств в вашем базовом классе NSObject
. К счастью, с userName
определением как a String!
, вы можете вызвать super.init()
перед собой, return nil
который запустит ваш NSObject
базовый класс и исправит ошибку компиляции.
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
логический параметр, позволяющий моему инициализатору вычислять свойства, которые могут или не могут быть созданы на лету. Например, еслиdateCreated
ключ отсутствует, и я могу установить свойство на лету, потому чтоcanSetCalculableProperties
параметр имеет значение true, я просто устанавливаю его на текущую дату.