转载

KVO这种黑科技

前几天写了一个下拉刷新的控件 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的消息传递,就像上边的例子那样,当更改属性的值后,监听对象会立即得到通知。

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

正文到此结束
Loading...