2015-03-12

前几天写了一个下拉刷新的控件YiRefresh用到了KVO,以前从不知道为什么别人说少用它。现在才知道真的要少用这个黑科技。文中的代码多事YiRefresh的。

先看一下我为什么要黑它,因为它让我看到了这个。

kvo

先说一下基本用法 step1

//    为_scrollView设置KVO的观察者对象,keyPath为contentOffset属性
    [_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

step2

//当属性的值发生变化时,自动调用此方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (![@"contentOffset" isEqualToString:keyPath])return;
}

完了,好像还有一个step3,先不添加,我们发现在YiRefresh的UITableView、UICollectionView的场景下不会出什么错,然后我就commit了。 然后今天想把UIWebView的使用场景加上去,因为UIWebView有一个属性scrollView,所以我就这样加了。

    //    YiRefreshHeader  头部刷新按钮的使用
    refreshHeader=[[YiRefreshHeader alloc] init];
    refreshHeader.scrollView=webView.scrollView;
    [refreshHeader header];
    refreshHeader.beginRefreshingBlock=^(){

        [webView loadRequest:[[NSURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"http://www.coderyi.com/"]]];


    };
   

到这里其实还是不会出现问题,shit!但是当block里面为空时,错误就来了。

思量很久之后,我就把传说中的step3加上 step3

-(void)dealloc{
    [_scrollView removeObserver:self forKeyPath:@"contentOffset"];
}

因为我发现只有被观察对象不是直接的对象UITableView或者UICollectionView而是UIWebView的scrollView的属性的时候,它才调用dealloc,并且这个时候如果不removeObserver就回报错。 这是因为UIWebView的scrollView作为属性时被retain了。

所以对于这个黑科技,不管被观察对象有没有被retain,都应该Observer对象和Observer者一一对应,多一个少一个都会报错,而且是闪退这种无法容忍的错。

KVO它来源于设计模式中的观察者模式,KVO是有一点用处的,KVO有时候会适用于Model和View的通信,就像上边的例子那样,当更改属性的值后,监听对象会立即得到通知。

关于KVO的原理,这里可以简单说一下(引用自sunnyxx的objc kvo简单探索):

1、当一个object有观察者时,动态创建这个object的类的子类

2、对于每个被观察的property,重写其set方法

3、在重写的set方法中调用- willChangeValueForKey:和- didChangeValueForKey:通知观察者

4、当一个property没有观察者时,删除重写的方法

5、当没有observer观察任何一个property时,删除动态创建的子类

这里还想对比一下KVO、NSNotification以及delegate,KVO、NSNotification都是观察者模式,可以一对多,并且不关注返回值;delegate是代理模式,只能一对一,关注返回值。

delegate的效率可能要比那两个高一点,而且也主张多用delegate,不过有时候它也会出错,所以需要在dealloc中置该对象的delegate为nil。

文章可能有不对不清楚的地方,请读者指教。

更多KVO的吐槽看这里,轻量级KVO[译]

KVO的详细使用看这里, [深入浅出Cocoa]详解键值观察(KVO)及其实现机理

更多黑科技看这里,ARC 下内存泄露的那些点