首页 > 代码库 > KVC & KVO 入门

KVC & KVO 入门

KVC:

简介:

全称 Key-Value Coding 。KVC是一种间接访问对象属性(用字符串表征)的机制,而不是直接调用对象的accessor(setter/getter)方法或是直接访问成员对象。KVC的key值必需小写,并且必须是对象内的属性或变量。可以访问一些没有暴露出来的变量。

使用:

[_bank setValue:@"I am Lee" forKey:@"name"];   // 设置值[_bank valueForKey:@"name"];  //读取值

可以看出KVC的使用是非常简单的,但是只有KVC是不够的,还需要结合KVO来做。

 

KVO:

简介:

当指定的对象的属性被修改了,允许对象接受到通知的机制。每次指定的被观察对象的属性被修改的时候,KVO都会自动的去通知相应的观察者。主要使用KVO来实现对象属性和变量的监听。当有属性改变,KVO会提供自动的消息通知。这样的架构有很多好处。首先,开发人员不需要自己去实现这样的方案:每次属性改变了就发送消息通知。这是KVO机制提供的最大的优点。因为这个方案已经被明确定义,获得框架级支持,可以方便地采用。开发人员不需要添加任何代码,不需要设计自己的观察者模型,直接可以在工程里使用。其次,KVO的架构非常的强大,可以很容易的支持多个观察者观察同一个属性,以及相关的值。总的来说,就是不需要自己去定义消息的通知机制,只需关心对象的值的变化。

使用:

定义Bank.h文件

////  Bank.h//  testDemo////  Created by stardust on 15-1-15.//  Copyright (c) 2015年 com. All rights reserved.//#import <Foundation/Foundation.h>@interface Bank : NSObject{    NSString *name;}@property NSInteger money;-(void)beRobbed;@end

Bank.m文件:

////  Bank.m//  testDemo////  Created by stardust on 15-1-15.//  Copyright (c) 2015年 com. All rights reserved.//#import "Bank.h"@implementation Bank//@synthesize money;-(void)beRobbed{    self.money = self.money - 100;}@end

APerson.h文件:

////  APeron.h//  testDemo////  Created by stardust on 15-1-15.//  Copyright (c) 2015年 com. All rights reserved.//#import <Foundation/Foundation.h>@interface APeron : NSObject@end

APerson.m文件:

////  APeron.m//  testDemo////  Created by stardust on 15-1-15.//  Copyright (c) 2015年 com. All rights reserved.//#import "APeron.h"@implementation APeron-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{    if ([keyPath isEqualToString:@"name"]) {        NSLog(@"KVC old name is %@ , new name is %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);    }    else if([keyPath isEqualToString:@"money"]){        NSLog(@"KVC old money is %@ , new money is %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);    }    else{        NSLog(@"KVC old value is %@ , new value is %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);      }}@end

主文件KVOController.m:

////  KVOViewController.m//  testDemo////  Created by stardust on 15-1-15.//  Copyright (c) 2015年 com. All rights reserved.//#import "KVOViewController.h"#import "Bank.h"#import "APeron.h"@interface KVOViewController ()@property APeron *aperson;@property Bank *bank;@end@implementation KVOViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.        _aperson = [[APeron alloc]init];    _bank = [[Bank alloc]init];        [_bank addObserver:_aperson forKeyPath:@"name" options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:@"hello"];    [_bank addObserver:_aperson forKeyPath:@"money" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:@"hello2"];    [_bank addObserver:_aperson forKeyPath:@"jack" options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:@"hello3"];        [_bank setValue:@"I am Lee" forKey:@"name"];    _bank.money = 101;    [_bank beRobbed];        NSLog(@"... %@",[_bank valueForKey:@"name"]);        //[_bank setValue:@"Tim Jack" forKey:@"jack"];  // 此句报错        

    // 一定要移除kvo,不然会有可能报错

    [_bank removeObserver:_aperson forKeyPath:@"name"];

    [_bank removeObserver:_aperson forKeyPath:@"money"];

    [_bank removeObserver:_aperson forKeyPath:@"jack"];

}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}/*#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {    // Get the new view controller using [segue destinationViewController].    // Pass the selected object to the new view controller.}*/@end

显示结果:

2015-01-15 19:36:52.256 testDemo[3442:634253] KVC old name is <null> , new name is I am Lee2015-01-15 19:36:52.257 testDemo[3442:634253] KVC old money is 0 , new money is 1012015-01-15 19:36:52.257 testDemo[3442:634253] KVC old money is 101 , new money is 12015-01-15 19:36:52.258 testDemo[3442:634253] ... I am Lee

 

通过以上可以看出,设置aperson来监听Bank对象的变化,监听变化的处理放在APerson中,只要Bank对象中被监听的值发生变化,无论是直接设置改变,还是通过KVC,都能监听得到并执行相关监听的逻辑。但是,对于不存在的值,例如主文件代码中注释了的这句:” [_bank setValue:@"Tim Jack" forKey:@"jack"];“,即使可以添加不存在值的监听,但是调用相应的KVC时,会crash,这可能跟KVC的机制有关。

 

参考:

1

 

KVC & KVO 入门