最近了解了一下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:有序一对多关系成员 NSArray
mutableSetValueForKey:无序一对多关系成员 NSSet
上代码:
#import "ViewController.h"
@interface BookModel :NSObject
{
NSString *name;
float price;
}
@end
@implementation BookModel
@end
@interfaceViewController ()
{
BookModel *_model;
UILabel *_label;
UIButton *_button;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
_model = [[BookModelalloc] init];
[_modelsetValue:@"语文"forKey:@"name"];
[_modelsetValue:@"20.0"forKey:@"price"];
[_modeladdObserver:selfforKeyPath:@"name"options:NSKeyValueObservingOptionNewcontext:nil];
[_modeladdObserver:selfforKeyPath:@"price"options:NSKeyValueObservingOptionNewcontext:nil];
_label = [[UILabelalloc] initWithFrame:CGRectMake(100,100, 200,30)];
_label.backgroundColor = [UIColorclearColor];
_label.layer.borderColor = [UIColorgreenColor].CGColor;
_label.layer.borderWidth =1.0;
_label.layer.masksToBounds =YES;
_label.text = [NSStringstringWithFormat:@"%@ - %@",[_modelvalueForKey:@"name"],[_modelvalueForKey:@"price"]];
[self.viewaddSubview:_label];
_button = [UIButtonbuttonWithType:UIButtonTypeCustom];
_button.frame =CGRectMake(100, CGRectGetMaxY(_label.frame) +30, 100, 30);
[_buttonsetTitle:@"改变价格"forState:UIControlStateNormal];
[_buttonsetTitleColor:[UIColorblueColor] forState:UIControlStateNormal];
[_buttonaddTarget:selfaction:@selector(buttonAction)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:_button];
}
- (void)buttonAction
{
[_modelsetValue:@"数学"forKey:@"name"];
[_modelsetValue:@"30.0"forKey:@"price"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPathisEqualToString:@"name"] || [keyPathisEqualToString:@"price"]) {
_label.text = [NSStringstringWithFormat:@"%@ - %@",[_modelvalueForKey:@"name"],[_modelvalueForKey:@"price"]];
NSLog(@"书本信息变为 %@",_label.text);
}
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// 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这两个文件。