iOS学习笔记8 - KVO与KVC

KVO和KVC分别是Key-Value Observing和Key-Value Coding的简称。想到这个话题是因为现在我写的tableView的更新是每隔数秒的轮询,在考虑是不是需要用个类似触发更新的机制。这自然就想到了观察者模式。

搜索Objective-c的观察者模式,发现在http://stackoverflow.com/questions/165790/whats-the-nicest-way-to-do-observer-observable-in-objective-c-iphone-version 中提到有两种方式可以实现:NSNotificationCenter和KVO。那个回答里形容Notification是较为古老而重型的。。。虽然我也稍微研究过,不过还是作为下次的话题吧。 

 

1. KVC

咦,不是要说KVO吗?为什么先要说KVC?Mac Developer Library说KVC是KVO的准备知识。好吧,先来看看KVC。

KVC是一种非直接访问对象属性的机制。什么是直接访问?get和set。

用省略过头的话来解释,KVC就是通过key来获取value。

有点像Dictionary?嗯,从某种意义上来说是,但远远不止。

在Objective-C下,也有一个字典类NSDictionary,可以通过objectForKey方法来获取某个key所对应的value。但KVC可以在所有类中使用valueForKey这个方法,来获取某个property(key)的值(value)。

来看看代码范例。例如有这么一个类:

@interface TestClass : NSObject

@property NSInteger integerProperty;

@property TestClass *linkedInstance;

@end

可以使用传统的set来赋值,例如:

    TestClass *anotherInstance = [[TestClassalloc] init];



    myInstance.linkedInstance = anotherInstance;



    myInstance.integerProperty = 2;

不过也可以用kvc来赋值:

    TestClass *anotherInstance = [[TestClass alloc] init];



    myInstance.linkedInstance = anotherInstance;



    [myInstance setValue:@2forKeyPath:@"linkedInstance.integerProperty"];

从这个角度上来说,KVC类似于.NET中反射的部分功能。

如上所述,要通过KVC取值,可以通过valueForKey。

由于是语言级别的功能,所以KVC能实现的功能挺强大。例如:

根据index来获取一个或数个:objectAtIndex, objectsAtIndexes, count, -get<Key>:range:

增删改:insertObject, insertObjects,removeObjectAtIndex, replaceObjectAtIndex, 

 

2. KVO

KVO的作用是允许某个对象得知其他对象的某个属性发生了改动。在MVC的model和controller层之间的交互中应用得特别广泛。

实现KVO需要三步:

1) 明确通知对象和被通知对象

例如:如果存款发生了变更,比如被提取了5000元,那么账户所有人就需要被告知。这个场景中,通知对象就是银行账户,被通知对象就是账户所有人

 

2) 被通知对象在通知对象中,注册对某个属性的观察者

语法为:addObserver:forKeyPath:options:context:

对于上面那个例子,所有者就需要在账户实例里注册一个观察者。

代码范例:

[account addObserver:inspector

              forKeyPath:@"openingBalance"

                 options:(NSKeyValueObservingOptionNew |

                          NSKeyValueObservingOptionOld)

                 context:NULL];

其中option的参数表示需要得知这个属性更改前和更改后的值。

另外,可以添加,自然也可以用removeObserver移除。

 

3) 被通知对象(观察者)实现observeValueForKeyPath方法

这个方法是用来实现当被通知后,观察者会做些啥反应

对于上面那个例子,如果观察者判断自己有没有进行过提款或购物操作,然后决定是不是报警?

代码范例:

- (void)observeValueForKeyPath:(NSString *)keyPath

                      ofObject:(id)object

                        change:(NSDictionary *)change

                       context:(void *)context {

    if ([keyPath isEqual:@"openingBalance"]) {

        [openingBalanceInspectorField setObjectValue:

         [change objectForKey:NSKeyValueChangeNewKey]];

    }

    /*

     Be sure to call the superclass's implementation *if it implements it*.

     NSObject does not implement the method.

     */

    [superobserveValueForKeyPath:keyPath

                         ofObject:object

                           change:change

                          context:context];

}

 

 

参考资料:

Key-Value Coding Programming Guide

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html%23//apple_ref/doc/uid/10000107-SW1

 

Key-Value Observing Programming Guide

http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html%23//apple_ref/doc/uid/10000177-BCICJDHA

你可能感兴趣的:(学习笔记)