Что вызвало ошибку "Константа, захваченная замыканием перед инициализацией"
В следующем классе
class Foo {
let _defaultValue = "N/A"
let value: String
init (dict: NSDictionary) {
self.value = dict["bar"] as? String! ?? _defaultValue
}
}
компиляция завершается с сообщениемconstant 'self.value' captured by a closure before being initialized
Насколько я вижу, нет операторов читает self.value
и это сообщение действительно сбивает с толку.
Обход, который я случайно изобрел, смущает меня еще больше:
class Foo {
let value: String
init (dict: NSDictionary) {
let _defaultValue = "N/A"
self.value = dict["bar"] as? String! ?? _defaultValue
}
}
Изготовление _defaultValue
объявленный и инициализированный внутри конструктор закрывает компилятор и программа работает!
Как объяснить такую вещь?
1 ответ
Причиной сообщения об ошибке является то, что оператор слияния ноль определяется как
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
и выполняет "автоматическое замыкание" по второму аргументу (чтобы получить короткое замыкание). Так
self.value = dict["bar"] as? String ?? _defaultValue
преобразуется компилятором в
self.value = dict["bar"] as? String ?? { self._defaultValue }()
а вот компилятор жалуется потому что self
захватывается до полной инициализации. (Сообщения об ошибках немного отличаются между Swift 2 и Swift 3).
Мне приходят на ум два обходных пути (возможно, у кого-то есть лучший): сначала вы можете назначить свойство локальной переменной:
init(dict: NSDictionary){
let defValue = _defaultValue
self.value = dict["bar"] as? String! ?? defValue
}
Или вы можете сделать это статическим свойством класса:
class Foo {
static let _defaultValue = "N/A"
let value: String
init(dict: NSDictionary) {
self.value = dict["bar"] as? String ?? Foo._defaultValue
}
}