美文网首页
ReactiveCocoa中的KVO和iOS原生KVO的对比

ReactiveCocoa中的KVO和iOS原生KVO的对比

作者: DevWin | 来源:发表于2018-01-12 16:17 被阅读0次

    首先说下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),出了代码块之后就被释放了
    
    1. rac_observeKeyPath的block内部需要注意循环引用使用全局变量和self都会引起内存泄漏,被监听者和监听者都无法释放.可以使用@weakify(self)和@strongify(self)来修饰一下,前提需要导入
    #import <RACEXTScope.h>
    

    5.调用多次dispose也不会引起crash.

    相关文章

      网友评论

          本文标题:ReactiveCocoa中的KVO和iOS原生KVO的对比

          本文链接:https://www.haomeiwen.com/subject/wxmfoxtx.html