首先说下iOS中的原生KVO:
原生KVO的主要使用方法是:
举例
self.p = [People new];
[self.p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew context:nil];
然后在当前类中实现下面的回调方法即可
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
NSLog(@"%d",self.p.age);
}
原生KVO的使用经常会遇到的两大错误:
错误1:An instance 0xxxxxx of class XXX was deallocated while key value observers were still registered with it.
这种错误出现的情况是被观察者self.p在被释放之前没有调用removeObserver来移除监听.但是在iOS11上苹果似乎解决了这个问题,不会crash了,但是低版本的iOS上依然会crash,所以如果想使用原生的KVO,那么该移除监听的时候还是得移除.
错误2:Cannot remove an observer XXX for the key path "age" from XXX because it is not registered as an observer
这种错误出现的情况是被观察self.p多次调用removeObserver移除监听对象会导致这个crash问题.另外,如果一个对象在没有调用addObserver之前,就调用removeObserver也会导致这个问题.
下面说说ReactiveCocoa中的KVO:
首先使用之前需要需要导入头文件:
#import <NSObject+RACKVOWrapper.h>
使用方法
全局对象
@property (nonatomic,strong) People *p;
@property (nonatomic,strong) RACDisposable *disposable;
self.p = [People new];
@weakify(self)
self.disposable = [self.p rac_observeKeyPath:@"age" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew observer:self block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
@strongify(self)
NSLog(@"%d",self.p.age);
}];
这里有几个注意事项:
1.上面observer可以为nil,但是我们一般使用self.
另外disposable需要使用强引用,如何使用weak修饰,那么disposable出了大括号{}之后就会被释放掉了.
2.如果需要取消一个监听直接调用下面的方法就可以了:
[self.disposable dispose];
3.我们不需要显示的调用dispose来移除监听,因为在observer被释放,或者被监听者self.p dealloc的时候会自动移除监听.
{
People *p = [People new];
[p rac_observeKeyPath:@"age" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew observer:p block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
}];
}
方法调用完毕之后,监听就自动移除了,因为这类的observer(对象p),出了代码块之后就被释放了
- rac_observeKeyPath的block内部需要注意循环引用使用全局变量和self都会引起内存泄漏,被监听者和监听者都无法释放.可以使用@weakify(self)和@strongify(self)来修饰一下,前提需要导入
#import <RACEXTScope.h>
5.调用多次dispose也不会引起crash.
网友评论