kvo和容器类

观察容器类通常会造成一些困扰。要牢记一点是观察容器类和观察其中的对象是不同的。
如果一个容器包含了Adam Bob和Carol,那么增加Denise就改变了容器。而改变Adam不会改变容器。

如果要观察容器中的对象的改变,必须观察那些对象,而不是容器本身。

一般来讲,可以先观察容器,在添加对象后观察对象,而在删除对象后停止观察对象。

在某种意义上,KVC是为了KVO的实现,下面重点说说KVO。KVO,即Key-Value Observing,也就是一个观察者模式,当一个对象的属性变化会收到对应的变化通知。变化的种类有四种,

typedef NS_OPTIONS(NSUInteger, NSKeyValueChange) { 
NSKeyValueChangeSetting = 1, 
NSKeyValueChangeInsertion = 2, 
NSKeyValueChangeRemoval = 3, 
NSKeyValueChangeReplacement = 4
};

其中NSKeyValueChangeSetting主要是对于一个对象地址的变化(或常量的变化),而后三个主要是对容器类的改变,举个例子,就是一个数组里新加一个item或者删掉一个item都会收到对应的通知,这就是kvo的强大之处了。

主要实现代码:监听property:

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

keyPath就是对应的property的string,context就是允许自己携带的上下文,在回调里会返回。
移除property的监听:

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

有一点必须注意,假如你没有监听这个property而调用移除,会导致系统崩溃。这里需要非常小心。

然后重写这个回调,当属性改变就会回调这个函数:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

keyPath就是对应的property,context就是监听手动设置的上下文,可以为NULL,字典里可以取到变化的type,原来的值和现在的值。

而要实现数组(或容器)里面item个数的变化,当然,有点不方便的是,当我们要获取这个TestItem的array时,不能简单用item.array,而必须调用
[[item mutableArrayValueForKey:@"array"] addObject:item];

只有用mutableArrayValueForKey得到的数组变化才会收到通知。
我们可以看看这样变化产生的change:

(lldb) po change$6 = 0x09169bc0 {
 indexes = "<NSIndexSet: 0x9169a10>[number of indexes: 1 (in 1 ranges), indexes: (0)]";
 kind = 2; 
new = ( "<TestItem: 0x7163cf0>" );
}

indexes描述了变化的index,kind = 2即上面所说的NSKeyValueChangeInsertion,代表数组新插入了一个数据,new就是一个增加的数据数组。其他两种类型的变化大家可以感受一下。
至于NSmutableDictionary的实现原理一样,就是把array换成dictionary即可。

转载地址:
http://www.cnblogs.com/vicstudio/p/3337952.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容