KVC和KVO看上去又是两个挺牛的单词简写,KVC是Key-Value Coding的简写,是键值编码的意思。KVO是Key-Value Observing的简写,是键值观察的意思。那么我们能拿KVC和KVO干些什么事呢?这两个缩写单词不能否认听起来挺高端的样子。这两个方法都是runtime方法,我们先来介绍KVC。
1.KVC(Key-Value Coding)键值编码
为了测试我们建立两个测试类
测试类一:
#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
测试类二:
#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: 来获取实例变量的值,废话少说,代码走起:
KVCClass *kvc = [KVCClass new];
//通过setValue: forKey:来动态设置属性的值
[kvc setValue:@"我是同过setValue方法设置的值" forKey:@"name"];
//通过valueForkey来获取值
NSLog(@"name = %@", [kvc valueForKey:@"name"]);
代码运行结果:
2014-08-14 16:08:57.940 Memory[1414:303] name = 我是同过setValue方法设置的值
(2)我们可以通过键路径给实例变量是其他类的对象赋值 setValue: forKeyPath:
代码如下: 接着上面的代码来得,KVC的一项实例变量是SubKVCClass的对象
//通过键路径来给KVCClass中的对象的属性赋值
SubKVCClass *sub = [SubKVCClass new];
kvc.subKVC = sub;
[kvc setValue:@"我是subName, 通过kvc的键路径来给我赋的值" forKeyPath:@"subKVC.subName"];
NSLog(@"subName = %@", [kvc valueForKeyPath:@"subKVC.subName"]);
NSLog(@"%@", kvc);
上面代码的运行结果:
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接口:
#import <Foundation/Foundation.h>
@interface KVOClass : NSObject
@property(strong,nonatomic) NSString * name;
@end
KVOClass实现
#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方法,第一个参数是观察那个类,第二个参数是那个类中的那个属性,第三个方法是观察选项,第四个会传到下面的观察方法中
上面的代码运行结果为:
2014-08-14 16:56:16.843 Memory[1483:303] name被改变啦!