为什么不在子对象上调用 KVO 观察器?

Why doesn't KVO observer get called on a sub object?

有了下面的 Swift 游乐场,为什么 view 里面的观察者永远不会被调用?

import Foundation

@objc class Person: NSObject {
    @objc dynamic var name = "Taylor Swift"
}

let taylor = Person()

taylor.observe(\Person.name, options: .new) { person, change in
    // we do get here
    print("I'm now called \(person.name)")
}

taylor.name = "Justin Bieber"

@objc class View: NSObject {
    var person = Person()

    override init() {
        person.observe(\Person.name, options: .new) { (person, change) in
            // we never get here
            print("I changed my name to \(person.name)")
        }
    }
}

let view = View()
let lewis = Person()
lewis.name = "Lewis"
view.person = lewis
view.person.name = "Lewis"
print(view.person.name)

why does the observer inside view never get called

有两个原因(即你做错了两件不相关的事情)。

  • 您已允许观察者消失。它由对 observe 的调用返回,但您没有捕获并保存它。所以观察在任何事情有机会发生之前就结束了。 (你在第一次观察时也犯了同样的错误,但你 运行 在游乐场的事实掩盖了它。这是为什么游乐场是魔鬼的工作的另一个例子。)

  • 您换了一个人 (view.person = lewis)。所以改名的人不是我们观察的那个人;我们观察的那个人已经不存在了

因此,此重写将修复它:

@objc class Person: NSObject {
    @objc dynamic var name = "Taylor Swift"
}

@objc class View: NSObject {
    var person = Person()
    var ob : NSKeyValueObservation?

    override init() {
        super.init()
        self.ob = self.person.observe(\.name, options: .new) { (person, change) in
            print("I changed my name to \(person.name)")
        }
    }
}

let view = View()
view.person.name = "Lewis"