KVC/KVO理解

KVC 与 KVO 是 Objective C 的关键概念,是必须要理解的东西

下面是实例讲解。

一、KVC – Key-Value Coding

KVC,即是指NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。

一个对象拥有某些属性。比如说,一个 Person 对象有一个 name 和一个 address 属性。以 KVC 说法,Person 对象分别有一个 value 对应他的 name 和 address 的 key。 key 只是一个字符串,它对应的值可以是任意类型的对象。从最基础的层次上看,KVC 有两个方法:

一个是设置 key 的值,

另一个是获取 key 的值。

如下面的例子:

// Person.h#import //@interfacePerson:NSObject

//@property(nonatomic,strong)NSString*name;

@property(nonatomic,strong)NSString*address;

@property(nonatomic,strong)Person*spouse;//@end

// ViewController.m

-(void)viewDidLoad{[superviewDidLoad];

//Person*person=[[Personalloc]init];person.name=@"Jack";person.address=@"chengdu";

//[selfchangePerson:personName:@"Kevin"];

}

//-(void)changePerson:(Person*)personName:(NSString*)newName{

// using the KVC accessor (getter) methodNSString*originalName=[personvalueForKey:@"name"];

//// using the KVC  accessor (setter) method.[personsetValue:newNameforKey:@"name"];

//NSLog(@"changed %@`s name to: %@",originalName,person.name);//输出:changed Jack`s name to: Kevin

}

现在,如果 Person 有另外一个 key 配偶(spouse),spouse 的 key 值是另一个 Person 对象,用 KVC 可以这样写:

-(void)viewDidLoad{

[superviewDidLoad];

//Person*person=[[Personalloc]init];

person.name=@"Jack";

person.address=@"chengdu";

//[selfchangePerson:personName:@"Kevin"];

//Person*spouse=[[Personalloc]init];spouse.name=@"Rose";spouse.address=@"chengdu";

//person.spouse=spouse;

//[selflogMarriage:person];}

//-(void)logMarriage:(Person*)person{

// just using the accessor again, same as example above

NSString*personName=[personvalueForKey:@"name"];

//// this line is different, because it is using

// a "key path" instead of a normal "key"

NSString*spouseName=[personvalueForKeyPath:@"spouse.name"];

//NSLog(@"%@ is happliy married to %@",personName,spouseName);//}

key与key path要区分开来,key可以从一个对象中获取值,而key path可以将多个 key 用点号 “.” 分割连接起来,比如上面例子中的:

[pvalueForKeyPath:@"spouse.name"];

相当于这样……

[[pvalueForKey:@"spouse"]valueForKey:@"name"];

好了,以上是 KVC 的基本知识,接着看看 KVO。

二、KVO – Key-Value Observing

Key-Value Observing (KVO)建立在 KVC 之上,它能够观察一个对象的 KVC key path 值的变化。举个例子,用代码观察一个 person 对象的 address 变化,以下是实现的三个方法:

watchPersonForChangeOfAddress:实现观察

observeValueForKeyPath:ofObject:change:context:在被观察的 key path 的值变化时调用。

dealloc停止观察

举个例子如下:

staticNSString*constKVO_CONTEXT_ADDRESS_CHANGED=@"KVO_CONTEXT_ADDRESS_CHANGED";

//@implementationViewController

//-(void)watchPersonForChangeOfAddress:(Person*)person{

// this begins the observing[personaddObserver:selfforKeyPath:@"address"options:0context:(__bridgevoid*_Nullable)(KVO_CONTEXT_ADDRESS_CHANGED)];

//// keep a record of all the people being observed,

// because we need to stop observing them in dealloc[m_observedPeopleaddObject:person];

}

//-(void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary*)changecontext:(void*)context{

//if(context==(__bridgevoid*_Nullable)(KVO_CONTEXT_ADDRESS_CHANGED)){NSString*name=[objectvalueForKey:@"name"];

NSString*address=[objectvalueForKey:@"address"];

NSLog(@"%@ has a new address: %@",name,address);}}

//-(void)dealloc{

//// must stop observing everything before this object is

// deallocated, otherwise it will cause crashes

for(Person*personinm_observedPeople){

[personremoveObserver:selfforKeyPath:@"address"];}m_observedPeople=nil;

}

@end

在这个例子中,当 person 的 aaddress 一旦发生改变,就会NSLog(@"%@ has a new address: %@", name, address);,这就是 KVO 的作用,它通过key path观察对象的值,当值发生变化的时候会收到通知。

你可能感兴趣的:(KVC/KVO理解)