Cuando uso el método KVO basado en el cierre de Swift 4, tengo un bloqueo en los dispositivos 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 = nilInformación del accidente:
*** Terminación de la aplicación debido a la excepción no detectada 'NSInternalInconsistencyException', razón: 'Se desasignó una instancia 0x de clase A mientras los observadores de valor clave aún estaban registrados en ella. Información de observación actual: (Contexto: 0x, Propiedad: 0x>
Busqué en Google y obtuve que era un error de Swift: https://bugs.swift.org/browse/SR-5816 , y una solución sería agregar las siguientes líneas dentro deinit
deinit { if #available(iOS 11.0, *) { } else { if let observation = self.observation { self.removeObserver(observation, forKeyPath: "value") } } }Mi pregunta es
¿Por qué el siguiente código no fallaría? (Simplemente cambiando la observación A por la observación B, que es miembro de 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 = nilMientras tanto, si agrego una solución anterior al código anterior, tengo un nuevo bloqueo, ¿por qué?
deinit { if let observation = self.observation { self.b.removeObserver(observation, forKeyPath: "value") } }Nuevo accidente:
*** Finalización de la aplicación debido a la excepción no detectada 'NSRangeException', razón: 'No se puede eliminar un observador para el "valor" de la ruta clave porque no está registrado como observador.'