KVC、KVO
很多语言如Java、C#等通过反射机制可以读写一个对象的属性,在一些特殊场合,这种方式可以方便管理对象属性。在OC中,我们不必进行任何操作就可以动态的读写属性值,这种方式就是KeyValue Coding,简称为KVC。
若要对象支持KVC操作,需要实现NSKeyValueCoding协议,而NSObject已实现该协议,所以OC中几乎所有的对象都支持KVC操作,该协议提供的方法如下:
l 动态设置
setValue:forKey;简单路径
setValue:forKeyPath;复合路径
l 动态读取
valueForKey:
valueForKeyPath:
案例:
//Account类
@interface Account : NSObject
@property(nonatomic,assign)NSInteger balance;//余额
@end
//Person类
@class Account;
@interface Person : NSObject
@property(nonatomic,copy) NSString * name;
@property(nonatomic,strong)Account * account;
@end
int main(int argc,const char * argv[])
{
@autoreleasepool
{
Account * account=[[Accountalloc] init];
Person * person=[[Personalloc] init];
//KVC
[person setValue:@"ssl"forKey:@"name"];
[person setValue:accountforKey:@"account"];
[person setValue:@12forKeyPath:@"account.balance"];
NSLog(@"name=%@,balance=%ld",person.name,person.account.balance);
}
return 0;
}
KVC使用起来比较简单,不管属性是公有的还是私有的,都可以进行读取和设置,但是它如何查找一个属性进行读取或设置呢?(假设对person的name属性进行读取)
l 首先调用setName方法,如果该方法不存在,则搜索成员变量_name,如果属性不存在,则调用setValue:forUndefinedKey:
l 调用name方法,如果没有则搜索_name成员变量,如果成员变量不存在,则调用valueForUndefinedKey;
在很多框架中,都支持双向绑定。如果数据模型发生改变,则通知响应的UI更新。在OC中,原生就支持该机制,叫做KeyValue Observing,简称KVO。KVO其实是一种观察者模式,利用它可以很容易实现视图和数据模型的分离,当数据模型发生改变时,作为监听器的视图组件就会被激发进行响应。在OC中要实现KVO必须实现NSKeyValueObserving协议。由于NSObject已实现该协议,因此OC的几乎所有对象都可以使用KVO。
使用KVO的步骤如下:
1) 注册指定key的监听器,addObserver:forKeyPath:option:context:监听器一般为视图组件,而数据模型为监听对象;
2) 实现回调监听:observeValueForKeyPath:ofObject:change:context:
3) 删除指定key的监听器,removeObserver:forKeyPath;
下面为Account实例的balance属性注册监听器,当balance属性发生改变时,激发监听器响应。
//Account类
@interface Account : NSObject
@property(nonatomic,assign)NSInteger balance;//余额
@end
//Person类
@class Account;
@interface Person : NSObject
@property(nonatomic,copy) NSString * name;
@property(nonatomic,strong)Account * account;
@end
#import "Person.h"
#import "Account.h"
@implementation Person
//注册监听器
-(void) setAccount:(Account *)account
{
_account=account;
[_account addObserver:self forKeyPath:@"balance" options:NSKeyValueObservingOptionNew context:nil];
}
//监听
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"balance"])
{
NSLog(@" balancechange...");
}
}
//删除监听器
-(void) dealloc
{
[_account removeObserver:self forKeyPath:@"balance"];
}
@end
//主函数
int main(int argc,const char * argv[])
{
@autoreleasepool
{
Account * account=[[Accountalloc] init];
Person * person=[[Personalloc] init];
//KVC
[person setValue:@"ssl"forKey:@"name"];
[person setValue:accountforKey:@"account"];
[person setValue:@12forKeyPath:@"account.balance"];
}
return 0;
}
原文地址:http://www.cnblogs.com/kenshincui/p/3871178.html