注意:

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath 
options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
 context:(nullable void *)context 
API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

1,使用kvo监听对象时,在对象销毁的时候,如果没有移除所有的监听者,将导致奔溃

Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'An instance 0x60800001dd20 of class Fizz was deallocated 
while key value observers were still registered with it.
 Current observation info: <NSKeyValueObservationInfo 0x60800003d320> (
<NSKeyValueObservance 0x608000057310: Observer: 0x7fa098f07590, Key path: number,
 Options: <New: YES, Old: YES, Prior: NO> Context: 0x0, Property: 0x608000057400>
)'

2,没有注册监听者时,如果进行移除监听者操作,也会奔溃

Terminating app due to uncaught exception 'NSRangeException', 
reason: 'Cannot remove an observer <ViewController 0x141e298e0> 
for the key path "text" from <UILabel 0x141e29de0> because it is not registered as an observer.'

3,提前释放监听者
在移除监听者之前,如果监听者被释放,当监听到事件的时候,程序奔溃;并且监听者被释放了,我们就无法正确的移除监听者了,被监听的对象释放时也会导致奔溃

4,上下文对象 context
如果传入了上下文对象,移除监听者时也需要传入上下文对象,使用相应的移除方法

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context

如何传入上下文对象

[self.label addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionOld context:(void *)@"dddd"];

获取上下文对象

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"context = %@", (__bridge NSString *)context);
}

资料

1,如何优雅地使用 KVO

results matching ""

    No results matching ""