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 = "[number of indexes: 1 (in 1 ranges), indexes: (0)]";
 kind = 2; 
new = ( "" );
}

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

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

你可能感兴趣的:(kvo和容器类)