Когда я использую следующий способ KVO на основе замыкания Swift 4, я получаю сбой на устройствах iOS 10
class A: NSObject {
@objc dynamic var value: Int = 0
var observation: NSKeyValueObservation?
override init() {
super.init()
// Crash
self.observation = self.observe(\A.value, options: [.new], changeHandler: { (_, change) in
})
}
}
var a: A? = A()
a = nil
Информация о сбое:
*** Из-за завершения приложениячтобы исключить исключение NSInternalInconsistencyException, причина: «экземпляр 0x класса A был освобожден, в то время как наблюдатели значения ключа все еще были зарегистрированы в нем.Информация о текущем наблюдении: (Контекст: 0x, Свойство: 0x>
Я гуглил и получил ошибку Swift: https://bugs.swift.org/browse/SR-5816,, и обходной путь будет добавлять следующие строки внутри deinit
deinit {
if #available(iOS 11.0, *) {
} else {
if let observation = self.observation {
self.removeObserver(observation, forKeyPath: "value")
}
}
}
Мой вопрос:
Почему следующий код не сработает? (Простое изменение наблюдения A на наблюдение B, являющегося членом A)
class A: NSObject {
@objc dynamic var value: Int = 0
var observation: NSKeyValueObservation?
let b = B()
override init() {
super.init()
self.observation = self.b.observe(\B.value, options: [.new], changeHandler: { (_, change) in
})
}
}
class B: NSObject {
@objc dynamic var value: Int = 0
}
var a: A? = A()
a = nil
Тем временем, если я добавляю предыдущий обходной путь к приведенному выше коду, я получаю новый сбой, почему?
deinit {
if let observation = self.observation {
self.b.removeObserver(observation, forKeyPath: "value")
}
}
Новыйсбой:
*** Завершение работы приложения из-за необработанного исключения «NSRangeException», причина: «Невозможно удалить наблюдателя для ключевого пути« значение »из-за того, что он не зарегистрирован в качестве наблюдателя».