KVC :Key-Value-Coding(键值编码)
一个非正式的 Protocol,提供一种机制来间接访问对象的属性
下面是使用KVC 和 不使用 KVC的代码对比
Persion *persion = [ [Persion alloc] init ];
//不使用KVC
persion.name = @"hufeng" ;
//使用KVC的写法
[persion setValue:@"hufeng" forKey:@"name"];
复杂点的:我们有一个人,这个人有一个手机类,这个手机类有一个电池类 我们要获取这个电池类
不用KVC:
Person *persion = [ [Person alloc] init ];
Phone *phone = person.phone;
Battery *battery = phone.battery;
使用KVC
Battery *battery = [person valueForKeyPath: @"phone.battery"];
//相当于
[[person valueForKey: @"phone"] valueForKey:@"battery"];
KVC可以被用到字典转模型中
- (id)initWithKVCDictionary:(NSDictionary *)KVCDic{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:KVCDic];
}
return self;
}
如果key不存在会崩溃,加以下代码解决:
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"key = %@",key);
}
如果key为id,可以这样处理:
- (void)setValue:(id)value forUndefinedKey:(nonnull NSString *)key {
if ([key isEqualToString:@"id"]) {
self.appId = (int)value;
}
}
KVO :Key-Value-Observing(键值观察)
提供了一种当其它对象属性被修改的时候能通知当前对象的机制。
KVO使用分三步:
(1)注册成为观察者
(2)观察者定义KVO的回调
(3)移除观察者
参考网上一篇文章:
1.假设一个场景,股票的价格显示在当前屏幕上,当股票价格更改的时候,实时显示更新其价格
@interface StockData : NSObject {
NSString * stockName;
float price;
}
@end
@implementation StockData
@end
2.定义此model为Controller的属性,实例化它,监听它的属性,并显示在当前的View里边
- (void)viewDidLoad
{
[super viewDidLoad];
stockForKVO = [[StockData alloc] init];
[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方法,修改对象的属性
-(void) buttonAction
{
[stockForKVO setValue:@"20.0" forKey:@"price"];
}
4. 实现回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"price"])
{
myLabel.text = [stockForKVO valueForKey:@"price"];
}
}
5.增加观察与取消观察是成对出现的,所以需要在最后的时候,移除观察者
- (void)dealloc
{
[super dealloc];
[stockForKVO removeObserver:self forKeyPath:@"price"];
[stockForKVO release];
}