kVC 与 KVO初始认识
最近了解了一下KVC与KVO。之前总觉得他们有多神秘,故了解了一下。都是实用的东西。
1、KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接收到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。这个观察者可以是被观察的对象,也就是说,自己观察自己。
方法/步骤:
1、通过addObserver: forKeyPath: options: context方法注册观察者,并制定观察的属性是什么。
2、当被观察的属性被修改后,实现回调方法 observeValueForKeyPath:ofObject:change:context
3、移除观察者
2、KVC是KeyValueCoding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。
当使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)时,KVC是关键技术。
关键方法定义在:NSKeyValueCodingprotocol
KVC支持类对象和内建基本数据类型。
valueForKey:,传入NSString属性的名字。
valueForKeyPath:,传入NSString属性的路径,xx.xx形式。
valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理。
setValue:forKey:
setValue:forKeyPath:
setValue:forUndefinedKey:
setNilValueForKey:当对非类对象属性设置nil时,调用,默认抛出异常。
mutableArrayValueForKey:有序一对多关系成员
mutableSetValueForKey:无序一对多关系成员
上代码:
#import "ViewController.h"
@interface BookModel : NSObject
{
NSString *name;
float price;
}
@end
@implementation BookModel
@end
@interface ViewController ()
{
BookModel *_model;
UILabel *_label;
UIButton *_button;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_model = [[BookModel alloc] init];
[_model setValue:@"语文" forKey:@"name"];
[_model setValue:@"20.0" forKey:@"price"];
[_model addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
[_model addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew context:nil];
_label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 200, 30)];
_label.backgroundColor = [UIColor clearColor];
_label.layer.borderColor = [UIColor greenColor].CGColor;
_label.layer.borderWidth = 1.0;
_label.layer.masksToBounds = YES;
_label.text = [NSString stringWithFormat:@"%@ - %@",[_model valueForKey:@"name"],[_model valueForKey:@"price"]];
[self.view addSubview:_label];
_button = [UIButton buttonWithType:UIButtonTypeCustom];
_button.frame = CGRectMake(100, CGRectGetMaxY(_label.frame) + 30, 100, 30);
[_button setTitle:@"改变价格" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[_button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_button];
}
- (void)buttonAction
{
[_model setValue:@"数学" forKey:@"name"];
[_model setValue:@"30.0" forKey:@"price"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"name"] || [keyPath isEqualToString:@"price"]) {
_label.text = [NSString stringWithFormat:@"%@ - %@",[_model valueForKey:@"name"],[_model valueForKey:@"price"]];
NSLog(@"书本信息变为 %@",_label.text);
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
跑一下程序看打印结果:
2014-12-18 11:45:23.549 KVODemo-1[988:48551] 书本信息变为 数学 - 20
2014-12-18 11:45:23.550 KVODemo-1[988:48551] 书本信息变为 数学 - 30
从打印结果可以看出,因为先对name属性做修改,所以先得到name属性修改的信息。这只是一些皮毛,没有挖掘深的东西。。如果想看深层的东西,可以看看Foundation框架里的NSKeyValueCoding.h 和 NSKeyValueObserving.h这两个文件。