iOS开发 KVC和KVO

一.KVC的使用与概述

KVC,即:Key-value coding,它是一种使用字符串标识符,间接访问对象属性的机制,它是很多技术的基础。
主要的方法就两个,setValue:forKeyvalueForKey
在Programming Guide中说,使用KVC可以简化代码,但事实上使用起来,还是要看具体情况。

代码实例:

1.首先定义两个DataModel,这种DataModel定义是无法访问属性的

1
2
3
4
5
6
7
8
@interface BookData : NSObject {  
NSString * bookName;
float price;
AuthorData * author;
}
@end
@implementation BookData
@end
1
2
3
4
5
6
@interface AuthorData : NSObject {  
NSString * name;
}
@end
@implementation AuthorData
@end

2.使用KVC

1
2
3
4
5
6
7
8
9
10
11
BookData * book1 = [[BookData alloc] init];  
[book1 setValue:@"english" forKey:@"bookName"];
[book1 setValue:@"20.0" forKey:@"price"];
AuthorData * author1 = [[AuthorData alloc] init];
[author1 setValue:@"tom" forKey:@"name"];
[book1 setValue:author1 forKey:@"author"];

NSLog(@"value=%@",[book1 valueForKey:@"bookName"]);
NSLog(@"price=%f",[[book1 valueForKey:@"price"] floatValue]);
NSLog(@"author=%@",[book1 valueForKeyPath:@"author.name"]);
[book1 release];

3.注意事项,在使用的时候,Key值不能写错,也就是属性的名字不能写错,大小写也是敏感的。
4.回到了最初的问题,应该什么时候使用KVC呢?
像上面的这种DataModel定义的方法,从程序员的角度讲,我感觉是不够规范的,起码应该保证正常访问,不管是用系统的get/set方式,或者是自己定义接口(getBookPrice,名字看起来友好一些的)。
在官方的Key-Value Observing Programming Guide中有段代码,演示如何简化代码了,有兴趣的朋友可以看看。

二.KVO的使用和概述

KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。

系统框架已经支持KVO,所以程序员在使用的时候非常简单。

  1. 注册,指定被观察者的属性,
  2. 实现回调方法
  3. 移除观察

假设一个场景,股票的价格显示在当前屏幕上,当股票价格更改的时候,实时显示更新其价格。

1.定义DataModel,

1
2
3
4
5
6
7
@interface StockData : NSObject {  
NSString * stockName;
float price;
}
@end
@implementation StockData
@end

2.定义此model为Controller的属性,实例化它,监听它的属性,并显示在当前的View里边

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (void)viewDidLoad  
{
[super viewDidLoad];

stockForKVO = [[StockData alloc] init];
[stockForKVO setValue:@"searph" forKey:@"stockName"];
[stockForKVO setValue:@"10.0" forKey:@"price"];
[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];

myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
myLabel.textColor = [UIColor redColor];
myLabel.text = [stockForKVO valueForKey:@"price"];
[self.view addSubview:myLabel];

UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
b.frame = CGRectMake(0, 0, 100, 30);
[b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:b];

}

3.当点击button的时候,调用buttonAction方法,修改对象的属性

1
2
3
4
-(void) buttonAction  
{
[stockForKVO setValue:@"20.0" forKey:@"price"];
}
  1. 实现回调方法
1
2
3
4
5
6
7
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context  
{
if([keyPath isEqualToString:@"price"])
{
myLabel.text = [stockForKVO valueForKey:@"price"];
}
}

5.增加观察与取消观察是成对出现的,所以需要在最后的时候,移除观察者

1
2
3
4
5
6
- (void)dealloc  
{
[super dealloc];
[stockForKVO removeObserver:self forKeyPath:@"price"];
[stockForKVO release];
}

KVO这种编码方式使用起来很简单,很适用与datamodel修改后,引发的UIVIew的变化这种情况,就像上边的例子那样,当更改属性的值后,监听对象会立即得到通知。

三.KVO和KVC实现机理分析

iPhone程序开发KVO/KVC实现机理分析是本文要介绍的内容,不多说,直接进入话题。我们来看详细内容。
Objective-C里面的Key-Value Observing (KVO)机制,非常不错,可以很好的减少浇水代码。关于KVO的学习,可以参考文章:《Key-Value Observing快速入门》:http://www.cocoadev.cn/Objective-C/Key-Value-Observing-Quick-Start-cn.asp

Key-Value Coding(KVC)实现分析

KVC运用了一个isa-swizzling技术。isa-swizzling就是类型混合指针机制。KVC主要通过isa-swizzling,来实现其内部查找定位的。isa指针,如其名称所指,(就是is a kind of的意思),指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针,和其它数据。

比如说如下的一行KVC的代码:

[site setValue:@"sitename" forKey:@"name"];

就会被编译器处理成:

1.SEL sel = sel_get_uid (“setValue:forKey:”);
2.IMP method = objc_msg_lookup (site->isa,sel);
3.method(site, sel, @”sitename”, @”name”);

首先介绍两个基本概念:

(1)SEL数据类型:它是编译器运行Objective-C里的方法的环境参数。
(2)IMP数据类型:他其实就是一个 编译器内部实现时候的函数指针。当Objective-C编译器去处理实现一个方法的时候,就会指向一个IMP对象,这个对象是C语言表述的类型(事实上,在Objective-C的编译器处理的时候,基本上都是C语言的)。
关于如何找到实现函数的指针,可参考文章:《Objective-C如何避免动态绑定,而获得方法地址》:http://www.cocoadev.cn/Objective-C/Get-method-address.asp

这下KVC内部的实现就很清楚的清楚了:一个对象在调用setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。

Key-Value Observing(KVO)实现

在上面所介绍的KVC机制上加上KVO的自动观察消息通知机制就水到渠成了。
当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。
熟悉KVO的朋友都知道,只有当我们调用KVC去访问key值的时候KVO才会起作用。所以肯定确定的是,KVO是基于KVC实现的。其实看了上面我们的分析以后,关系KVO的架构的构思也就水到渠成了。
因为KVC的实现机制,可以很容易看到某个KVC操作的Key,而后也很容易的跟观察者注册表中的Key进行匹对。假如访问的Key是被观察的Key,那么我们在内部就可以很容易的到观察者注册表中去找到观察者对象,而后给他发送消息。

小结:iPhone程序开发 KVO/KVC实现机理分析的内容介绍完了,希望本文对你有所帮助。

KVC和KVO的使用原则:

一、KVC(key-value-coding)

1、只针对类属性,设置键值对
2、设置setValue: forKey:,即forKey只能为类属性
3、取值valueForKey

二、KVO(key-value-observing)被观察者的属性发生改变时,通知观察者

1、利用KVC对类属性进行设置
2、注册observing对象addObserver:forKeyPath:options:context:
3、观察者类必须重写方法observeValueForKeyPath:ofObject:change:context:
4、应用,MVC模型中,数据库(dataModal)发生变化时,引起view改变,用这种方式实现非常方便

文章目录
  1. 1. 一.KVC的使用与概述
  2. 2. 二.KVO的使用和概述
    1. 2.1. 三.KVO和KVC实现机理分析
      1. 2.1.1. Key-Value Coding(KVC)实现分析
      2. 2.1.2. Key-Value Observing(KVO)实现