KVC/KVO

来源:互联网 发布:js获取div的value值 编辑:程序博客网 时间:2024/05/17 07:43

简介:
有许多人不懂kvc和kvo, 虽然经常提起这两个词,下面就具体介绍这两个分别代表什么和简单用法

1.用 KVC 实现高阶消息传递

valueForKey: 有很多有用的特例,比如说 NSArray 和 NSSet 这样的容器类都覆盖了这个方法。valueForKey: 被传递给容器中得每一个对象,而不是对容器本身进行操作。结果会被添加进返回的容器中。这样,开发者能很方便的用一个容器创建另一个容器对象,比如像这样:

NSArray *array = @[@"foo",@"bar",@"baz"];  NSArray *capitals = [array valueForKey:@"capitalizedString"];  

方法 capitalizedString 被传递给 NSArray 中的每一项,并返回一个包含结果的新 NSArray 。把消息(capitalizedString)作为参数传递称为高阶消息传递(Higher Order Messaging)。多个消息可以用键路径传递:

NSArray *array = @[@"foo",@"bar",@"baz"];  NSArray *capitalLengths = [array valueForKeyPath:@"capitalizedString.length"];  

以上代码对 array 的每一个元素调用 capitalizedString ,然后调用 length ,在把返回值封装进 NSNumber 对象。结果被收集进名为 capitalLengths 的新数组。

KVC 还提供了很复杂的函数,比如说自动对一组数字求和或者求平均值。看一下这个例子:

NSArray *array = @[@"foo",@"bar",@"baz"];  NSUInteger totalLenth = [[array valueForKeyPath:@"@sum.length"] intValue]; 

@sum 是一个操作符,对指定的属性(length)求和。注意,这种写法可能比等价的循环写法慢几百倍。
在处理有几千个或者几万个元素的数组时,性能问题通常会至关重要。除了 @sum ,在 IOS 开发者库的 Key-Value Coding Programming Guide 中还有很多其他的操作符。这些操作符在处理 Core Data 时尤其有用,而且比等价的循环写法快,因为它们优化为数据库查询操作。不过你不能创建自己的

2.KVO
KVO是Cocoa的一个重要机制,他提供了观察某一属性变化的方法,极大的简化了代码。这种观察-被观察模型适用于这样的情况,比方说根据A(数据类)的某个属性值变化,B(view类)中的某个属性做出相应变化。对于推崇MVC的cocoa而言,KVO应用的地方非常广泛。(这样的机制听起来类似Notification,但是notification是需要一个发送notification的对象,一般是notificationCenter,来通知观察者。而KVO是直接通知到观察对象。)

使用KVO时通常遵循如下的流程:

1、注册观察

[objc] view plain copy
print?在CODE上查看代码片派生到我的代码片

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

keyPath就是要观察的属性值,options给你观察键值变化的选择,而context方便传输你需要的数据(注意这是一个void型)

2、实现变化后的回调方法

[objc] view plain copy
print?在CODE上查看代码片派生到我的代码片

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

change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。

3、停止观察

[objc] view plain copy
print?在CODE上查看代码片派生到我的代码片

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

在 KVCTableViewCell 中,我们根据请求用 addObservation 观察目标的属性。注册 KVO 时,要把 self 作为 context 指针传递,以便在回调中判断这是否是我们观察的事件。因为一个类只能有一个 KVO 回调,所以可能收到父类注册的属性变化事件。如果是这样,需要把回调传递给 super。不幸的是,我们不能总是传给 super,因为 NSObject 可能抛出异常。所以要用唯一的 context 来识别观察的事件。

在 KVCTableViewController 中,我们创建了一个属性 now,并且让表格单元观察此属性。每隔一秒,数据源都会更新一次。观察者就会得到通知,表格单元也会更新。这是灰常高效的,在任何时候,都只有一屏的表格单元,因为单元是可以重用的。

KVO 真正的威力表现在 [KVCTableViewController updateNow] 方法:

[objc] view plain copy
print?在CODE上查看代码片派生到我的代码片

- (void)updateNow {    self.now = [NSDate date];  }  

唯一要做得就是更新数据。不需要操心谁在观察你,如果没有人观察你,那么就不存在任何 NSNotificationCenter 那样的开销。KVO 真正的优势就在于模型类不可思议的简洁性。只要用存取方法来修改实例变量,所有的观察机制都会自动生效,不需要付出任何成本。所有的复杂性都转移到了观察者而不是被观察者。

参考:http://blog.csdn.net/chaoyuan899/article/details/44699503

0 0