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 Lee

2015-01-15 19:36:52.257 testDemo[3442:634253] KVC old money is 0 , new money is 101

2015-01-15 19:36:52.257 testDemo[3442:634253] KVC old money is 101 , new money is 1

2015-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

 

你可能感兴趣的:(入门)