iOS的KVO与KVC

KVO

http://blog.csdn.net/sakulafly/article/details/14084183


  KVO的是Key Value Observe的缩写,中文是键值观察。这是一个典型的观察者模式,观察者在键值改变时会得到通知。iOS中有个Notification的机制,也可以获得通知,但这个机制需要有个Center,相比之下KVO更加简洁而直接。
      KVO的使用也很简单,就是简单的3步。
      1.注册需要观察的对象的属性addObserver:forKeyPath:options:context:
      2.实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用
      3.取消注册观察removeObserver:forKeyPath:context:


     不多说了,上代码:

@interface myPerson : NSObject
{
    NSString *_name;
    int      _age;
    int      _height;
    int      _weight;
}
@end

@interface testViewController : UIViewController
@property (nonatomic, retain) myPerson *testPerson;

- (IBAction)onBtnTest:(id)sender;
@end

- (void)testKVO
{
    testPerson = [[myPerson alloc] init];
    
    [testPerson addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"height"]) {
        NSLog(@"Height is changed! new=%@", [change valueForKey:NSKeyValueChangeNewKey]);
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (IBAction)onBtnTest:(id)sender {
    int h = [[testPerson valueForKey:@"height"] intValue];    
    [testPerson setValue:[NSNumber numberWithInt:h+1] forKey:@"height"];
    NSLog(@"person height=%@", [testPerson valueForKey:@"height"]);
}

- (void)dealloc
{
    [testPerson removeObserver:self forKeyPath:@"height" context:nil];
    [super dealloc];
}

第一段代码声明了myPerson类,里面有个_height的属性。在testViewController有一个testPerson的对象指针。
      在testKVO这个方法里面,我们注册了testPerson这个对象height属性的观察,这样当testPerson的height属性变化时,会得到通知。在这个方法中还通过NSKeyValueObservingOptionNew这个参数要求把新值在dictionary中传递过来。
      重写了observeValueForKeyPath:ofObject:change:context:方法,这个方法里的change这个NSDictionary对象包含了相应的值。
      需要强调的是KVO的回调要被调用,属性必须是通过KVC的方法来修改的,如果是调用类的其他方法来修改属性,这个观察者是不会得到通知的。

       因为Cocoa是严格遵循MVC模式的,所以KVO在观察Modal的数据变化时很有用。那么KVO是怎么实现的呢,苹果官方文档上说的比较简单:“Automatic key-value observing is implemented using a technique called isa-swizzling.”
       “When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. As a result the value of the isa pointer does not necessarily reflect the actual class of the instance.”
        就是说在运行时会生成一个派生类,在这个派生类中重写基类中任何被观察属性的 setter 方法,用来欺骗系统顶替原先的类。


KVC

  KVC是Key Value Coding的缩写,意思是键值编码。在iOS中,提供了一种方法通过使用属性的名称(也就是Key)来间接访问对象的属性方法。说的有的拗口,实际上就是通过类定义我们可以看到类的各种属性,那么使用属性的名称我们就能访问到类实例化后的对象的这个属性值。

      这个方法可以不通过getter/setter方法来访问对象的属性。因为一个类的成员变量如果没有提供getter/setter的话,外界就失去了对这个变量的访问渠道。而KVC则提供了一种访问的方法,这个在某些场合会很有威力。

 不多说了,上代码:

@interface myPerson : NSObject
{
    NSString *_name;
    int      _age;
    int      _height;
    int      _weight;
}
@end


@interface testViewController : UIViewController

@property (nonatomic, retain) myPerson *testPerson;

@end

- (void)testKVC
{
    testPerson = [[myPerson alloc] init];
    
    NSLog(@"testPerson's init height = %@", [testPerson valueForKey:@"height"]);
    [testPerson setValue:[NSNumber numberWithInt:168] forKey:@"height"];
    NSLog(@"testPerson's height = %@", [testPerson valueForKey:@"height"]);
}

第一段代码是定义了一个myPerson的类,这个类有一个_height的属性,但是没有提供任何getter/setter的访问方法。同时在testViewController这个类里面有一个myPerson的对象指针。

        当myPerson实例化后,常规来说是无法访问这个对象的_height属性的,不过通过KVC我们做到了,代码就是testKVC这个函数。

        运行之后打印值就是:

2013-11-02 11:16:21.970 test[408:c07] testPerson's init height = 0

2013-11-02 11:16:21.971 test[408:c07] testPerson's height = 168

    这就说明确实读写了_height属性。


    KVC的常用方法:

- (id)valueForKey:(NSString *)key;
- (void)setValue:(id)value forKey:(NSString *)key;

valueForKey的方法根据key的值读取对象的属性,setValue:forKey:是根据key的值来写对象的属性。


    这里有几个要强调一下

1. key的值必须正确,如果拼写错误,会出现异常

2. 当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来

3. 因为类key反复嵌套,所以有个keyPath的概念,keyPath就是用.号来把一个一个key链接起来,这样就可以根据这个路径访问下去

4. NSArray/NSSet等都支持KVC



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值