Почему наблюдатель KVO не вызывается на подобъекте? - PullRequest
0 голосов
/ 13 сентября 2018

На следующей игровой площадке 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)

1 Ответ

0 голосов
/ 14 сентября 2018

почему внутренний взгляд наблюдателя никогда не вызывается

Есть две причины (т. Е. Вы неправильно сделали две несвязанные вещи).

  • Вы позволили наблюдателю исчезнуть. Он возвращается при вызове на 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"
...