iOS 10设备上基于怪异Swift 4封闭的KVO错误

时间:2019-02-17 04:37:57

标签: ios swift key-value-observing

当我使用以下基于Swift 4基于闭包的KVO方式时,我在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'终止了应用程序,原因:'类A的实例0x被释放,而键值观察器仍在其中注册。当前观察信息:(上下文:0x,属性:0x>

我用Google搜索,发现它是一个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")
        }
    }
}

我的问题是

  1. 为什么下面的代码不会崩溃? (只需将观察者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
    
  2. 同时,如果我在上面的代码中添加了先前的解决方法,我将发生新的崩溃,为什么?

    deinit {
        if let observation = self.observation {
            self.b.removeObserver(observation, forKeyPath: "value")
        }
    }
    

新的崩溃:

  

***由于未捕获的异常'NSRangeException'而终止应用程序,原因:'由于未将键路径“值”的观察者注册为观察者,因此无法将其移除。”

0 个答案:

没有答案