KVC & KVO
KVC和KVO看上去又是两个挺牛的单词简写,KVC是Key-Value Coding的简写,是键值编码的意思。KVO是Key-Value Observing的简写,是键值观察的意思。那么我们能拿KVC和KVO干些什么事呢?这两个缩写单词不能否认听起来挺高端的样子。这两个方法都是runtime方法,我们先来介绍KVC。
1.KVC(Key-Value Coding)键值编码
为了测试我们建立两个测试类
测试类一:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#import <Foundation/Foundation.h> @ class SubKVCClass; @interface KVCClass : NSObject @property(copy ,nonatomic) NSString *name; @property(retain, nonatomic) SubKVCClass *subKVC; @end #import "KVCClass.h" #import "SubKVCClass.h" @implementation KVCClass -(NSString *)description { NSString *str = [NSString stringWithFormat:@ "property = %@, subName = %@" , _name, _subKVC.subName]; return str; } @end |
测试类二:
1
2
3
4
5
6
7
8
9
|
#import <Foundation/Foundation.h> @interface SubKVCClass : NSObject @property (copy, nonatomic) NSString *subName; @end #import "SubKVCClass.h" @implementation SubKVCClass @end |
(1)我们可以用键值编码给对象的属性动态赋值(必须得有标准的getter和setter方法,或者用@property声明)
我们可以调用setValue: forKey: 方法以字符串的相识向对象发送消息,可以设置实例变量的值。第一个参数是要设置的值,第二个参数是实例变量的名称
我们可以调用valueForKey: 来获取实例变量的值,废话少说,代码走起:
1
2
3
4
5
|
KVCClass *kvc = [KVCClass new ]; //通过setValue: forKey:来动态设置属性的值 [kvc setValue:@ "我是同过setValue方法设置的值" forKey:@ "name" ]; //通过valueForkey来获取值 NSLog(@ "name = %@" , [kvc valueForKey:@ "name" ]); |
代码运行结果:
1
|
2014-08-14 16:08:57.940 Memory[1414:303] name = 我是同过setValue方法设置的值 |
(2)我们可以通过键路径给实例变量是其他类的对象赋值 setValue: forKeyPath:
代码如下: 接着上面的代码来得,KVC的一项实例变量是SubKVCClass的对象
1
2
3
4
5
6
|
//通过键路径来给KVCClass中的对象的属性赋值 SubKVCClass *sub = [SubKVCClass new ]; kvc.subKVC = sub; [kvc setValue:@ "我是subName, 通过kvc的键路径来给我赋的值" forKeyPath:@ "subKVC.subName" ]; NSLog(@ "subName = %@" , [kvc valueForKeyPath:@ "subKVC.subName" ]); NSLog(@ "%@" , kvc); |
上面代码的运行结果:
1
2
|
2014-08-14 16:08:57.941 Memory[1414:303] subName = 我是subName, 通过kvc的键路径来给我赋的值 2014-08-14 16:08:57.942 Memory[1414:303] property = 我是同过setValue方法设置的值, subName = 我是subName, 通过kvc的键路径来给我赋的值 |
KVC的基本内容概就这些吧,当然啦还有在数组中使用KVC以及KVC中的运算-集合等,不做赘述啦。
2.介绍完KVC那么我们来介绍一下KVO,键值观察
键值观察是个什么东西啊?他有什么用啊?怎么用?从字面意思上说键值观察就是观察属性值的变化,也是运行时的方法,当实例变量改变时,系统会自动采取一些动作。
KVO使用三步走:
(1)注册成为观察者
(2)观察者定义KVO的回调
(3)移除观察者
来点实际的,还得上代码:
KVOClass接口:
1
2
3
4
5
|
#import <Foundation/Foundation.h> @interface KVOClass : NSObject @property(strong,nonatomic) NSString * name; @end |
KVOClass实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#import "KVOClass.h" @implementation KVOClass //在init注册观察者 -(id) init { if (self = [super init]) { [self addObserver:self forKeyPath:@ "name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@ "name" ]; } return self; } //重写观察方 - ( void )observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:( void *)context { if (context == @ "name" ) { NSLog(@ "name被改变啦!" ); } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } //移除观察者 -( void ) dealloc { [self removeObserver:self forKeyPath:@ "name" ]; [super dealloc]; } @end |
代码说明:注册观察者的时候调用addObserver方法,第一个参数是观察那个类,第二个参数是那个类中的那个属性,第三个方法是观察选项,第四个会传到下面的观察方法中
上面的代码运行结果为:
1
|
2014-08-14 16:56:16.843 Memory[1483:303] name被改变啦!
|