Вам необходимо использовать @objc
в вашем методе keyPathsForValuesAffecting
, чтобы механизм KVO мог найти его с помощью среды выполнения Objective C:
@objc class func keyPathsForValuesAffectingFullName() -> Set<NSObject> {
return ["name, "surname"]
}
Кстати, вместо этого вы можете использовать свойство и специальную форму #keyPath
, чтобы компилятор помог вам обнаруживать ошибки:
@objc class var keyPathsForValuesAffectingFullName: Set<String> {
return [#keyPath(name), #keyPath(surname)]
}
Вы также должны использовать dynamic
в свойствах восходящего потока (name
и surname
), как советовал Кен Томасес.
Вот полная программа тестирования (как программа командной строки macOS):
import Foundation
class DependencyTest: NSObject {
@objc dynamic var fullName: String {
return name + " " + surname
}
@objc dynamic var name = ""
@objc dynamic var surname = ""
@objc class var keyPathsForValuesAffectingFullName: Set<String> {
return [#keyPath(name), #keyPath(surname)]
}
}
class Observer: NSObject {
@objc let dep: DependencyTest
init(dep: DependencyTest) {
self.dep = dep
super.init()
addObserver(self, forKeyPath: #keyPath(Observer.dep.fullName), options: .prior, context: nil)
}
deinit {
removeObserver(self, forKeyPath: #keyPath(Observer.dep.fullName), context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("kvo: \(keyPath!) \(change?[.notificationIsPriorKey] as? Bool ?? false ? "prior" : "post")")
}
}
let d = DependencyTest()
let o = Observer(dep: d)
d.name = "Robert"
Выход:
kvo: dep.fullName prior
kvo: dep.fullName post
Program ended with exit code: 0