参照: KVC & KVO 来源一: 很基础的一篇
KVO入门 来源二:
KVO进阶 来源三: 这篇比较深入,考虑也很周全
来源四:
- 1.remove观察者
*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <SubViewController 0x7ff158707f80> for the key path "age" from <SubViewController 0x7ff158707f80> because it is not registered as an observer.'
修改前代码
// 添加观察者
Person *person = [[Person alloc] init];
person.name = @"hello";
person.age = 23;
self.subPersonKVO = person;
[self.subPersonKVO addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"SubViewController"];
// 移除观察者 在dealloc中
[self removeObserver:self forKeyPath:@"age" context:@"SubViewController"];
============= 解决方案
// 移除观察者 在dealloc中
[self.subPersonKVO removeObserver:self forKeyPath:@"age" context:@"SubViewController"];
self
-> self.subPersonKVO
关键点就在这里,观察谁,谁就应该移除
- 2.值修改了,但是并没有接收到
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<SubViewController: 0x7fc273d13450>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: age
解决方案:添加该方法
`- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
NSLog(@"keyPath=%@", keyPath);
self.subLabelKVO.text = [NSString stringWithFormat:@"%@现在的年龄是: %zd", self.subPersonKVO.name, self.subPersonKVO.age];
}
- 3.context上下文不一致,也可以理解为标识符不统一
*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <SubViewController 0x7fc175001d60> for the key path "age" from <Person 0x7fc172da5be0> because it is not registered as an observer.'
修改前
`- (void) kvo {
Person *person = [[Person alloc] init];
person.name = @"hello";
person.age = 23;
self.subPersonKVO = person;
[self.subPersonKVO addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"SubViewController"];
}
`- (void)dealloc {
[self.subPersonKVO removeObserver:self forKeyPath:@"age" context:nil];
}
====== 解决方案:context 统一
`- (void)dealloc {
[self.subPersonKVO removeObserver:self forKeyPath:@"age" context:@"SubViewController"];
}
一般来说context都是nil
,但是个人还是觉得区别开来为好