ios - KVO keyPathsForValuesAffecting 不起作用
问题描述
我的方法有问题keyPathsForValuesAffecting<key>
。我想通知观察者fullName
何时name
或surname
发生了变化。但不幸的是,没有通知观察员。
我的代码:
将被观察的类:
class DependencyTest: NSObject {
@objc dynamic var fullName: String {
return name + " " + surname
}
@objc var name = ""
@objc var surname = ""
class func keyPathsForValuesAffectingFullName() -> Set<NSObject> {
return ["name" as NSObject, "surname" as NSObject]
}
}
观察者视图控制器:
let dep = DependencyTest()
override func viewDidLoad() {
super.viewDidLoad()
addObserver(self, forKeyPath: "dep.fullName", options: .prior, context: nil)
dep.name = "bob" // Im expecting that `observeValue:` method will be fired
dep.surname = "gril"
}
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
print("" + keyPath!) // not called
}
谢谢!
解决方案
您需要@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)]
}
正如 Ken Thomases 建议的那样,您还应该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
推荐阅读
- sql - 视图表的 SQL 查询
- python - 如何使用经过训练的 XGB 分类模型预测新数据行?
- python - 如何使用带有按钮的 lambda 删除 tkinter 窗口
- elasticsearch - ElastAlert 获得 0 次点击
- java - 如何在 java .wav 文件中将小端转换为大端
- python - Django formset工厂获取错误对象没有属性保存
- python - 试图纠正异常值,但它说我正在从明显不推荐使用的参差不齐的嵌套序列创建一个 nd 数组
- wordpress - Wordpress - 如何在社交分享中添加自定义文本和链接?
- javascript - 在一个循环中抓取接下来的 N 个项目
- python - Pytorch 中两个类的一个热编码