Key-Value Coding KVC
一个对象拥有某些属性。比如说,一个kvc对象有一个 name 和一个 age 属性。以 KVC 说法,kvc 对象分别有一个 value 对应他的 name 和 age 的 key。 key 只是一个字符串,它对应的值可以是任意类型的对象。从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另一个是获取 key 的值。
如下:
.m文件里的属性,.h 里没有公开get和set方法,这时候我们要对里面的值进行修改。
@implementation KvcClass{
NSString *_name;
NSInteger _age;
FullName * full;
}
@end
KvcClass * myKVC = [[KvcClass alloc]init];
NSLog(@"%@",[myKVC valueForKey:@"name" ]);
[myKVC setValue:@"王哈哈" forKey:@"name"];
NSLog(@"%@",[myKVC valueForKey:@"name"]);
打印日志:
2016-03-02 17:23:48.291 test[3915:1461425] (null)
2016-03-02 17:23:50.001 test[3915:1461425] 王哈哈
支持NSDictionary赋值
NSDictionary * dic = [[NSDictionary alloc]initWithObjectsAndKeys:@"wang",@"name", [NSNumber numberWithInt:34],@"age", nil];
[myKVC setValuesForKeysWithDictionary:dic];
NSLog(@"%@",[myKVC valueForKey:@"name"]);
NSLog(@"%@",[myKVC valueForKey:@"age"]);
日志:
2016-03-02 17:24:13.027 test[3915:1461425] wang
2016-03-02 17:24:13.028 test[3915:1461425] 34
valueForKeyPath的使用
@implementation FullName{
NSString *first;
NSString *Second;
}
FullName* full = [[FullName alloc]init];
[full setValue:@"王" forKey:@"first"];
[myKVC setValue:full forKeyPath:@"full"];
NSString *firstname = [myKVC valueForKeyPath:@"full.first"];
NSLog(@"%@",firstname);
日志:
2016-03-02 17:27:06.036 test[3915:1461425] 王
Key-Value Observing (KVO)
Key-Value Observing (KVO) 建立在 KVC 之上,它能够观察一个对象的 KVC key path 值的变化。举个例子,用代码观察一个 kvc 对象的 name 变化,以下是实现的三个方法:
- watchPersonForChangeOfAddress: 实现观察
- observeValueForKeyPath:ofObject:change:context: 在被观察的 key path 的值变化时调用。
- dealloc 停止观察
@implementation KvoClass
NSMutableArray *m_observedPeople;
-(id) init;
{
if(self = [super init]){
m_observedPeople = [NSMutableArray new];
}
return self;
}
-(void) watchPersonForChangeOfAddress:(KvcClass *)p
{
// this begins the observing
[p addObserver:self
forKeyPath:@"full.first"
options:0
context:@"发生了改变"];
// keep a record of all the people being observed,
// because we need to stop observing them in dealloc
[m_observedPeople addObject:p];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
// use the context to make sure this is a change in the address,
// because we may also be observing other things
if(context == @"发生了改变") {
NSString *name = [object valueForKey:@"name"];
NSNumber *age = [object valueForKey:@"age"];
NSLog(@"%@ has a new name&age: %@", name, age);
}
}
KvoClass *myKVO = [[KvoClass alloc]init];
[myKVO watchPersonForChangeOfAddress:myKVC];
FullName* full = [[FullName alloc]init];
[full setValue:@"王" forKey:@"first"];
[myKVC setValue:full forKeyPath:@"full"];//调用这里first发生变化,回调observeValueForKeyPath。
//observeValueForKeyPath的回调只有kvc模式更改才能触发,通过一般的set方法是不能触发的。