iOS之KVC、KVO

KVC基本概念:

a.kvc又称键值编码,是一种用于间接访问对象属性的机制,使用此机制不需要调用对象的存取(get和set)方法,也不用调用实例变量就能访问对象的属性,即使对象的属性为私有变量,kvc也能对此变量进行存取操作;

 

b.kvc的方法(-setValue: forKey: 和 -valueForKey:)有NSObject的非正式协议(类别)NSKeyValueCoding中被申明;

 

KVC的基本用法:

1.设置和访问:

kvc中的基本调用方法包括-setValue: forKey: 和 -valueForKey:这两个方法,他们以字符串形式向对象发送消息;

 

  1. 例:  
 
  1. Book *book = [[Book alloc] init];  
  2. [book setValue:@"ios编程思想" forKey:@"bookName"];  
  3. NSLog(@"book:%@",[book valueForKey:@"bookName"]);  

是否存在setter  getter方法,如果不存在,将在内部查找名称为_key 或 key的实例变量,通过kvc,可以获取不存在getter方法的对象值,无需通过对象的指针访问。

 

需要注意的是,当我们通过setValue: forKey:设置对象的值或通过valueForKey:获取对象的值时,如果对象的实力变量为基本类型(char ,int ,float,bool),我们需要对数据进行封装

 

2.路径:方法(-setValue: forKeyPath: 和 -valueForKeyPath:)

除了通过key设置value外,kvc还支持路径,象文件路径一样,路径之间用" . "号隔开;

例:书对象中有个作者对象,作者对象中有name属性,通过book设置和获取到作者的name

 

  1. Book *book = [[Book alloc] init];  
  2. [book  setValue:@"wxxu"  forKeyPath:@"author.name"];  
  3. [book valueForKeyPath:@"author.name"];  

 

 

3.一对多的关系:

如果向一个NSArray数组中请求一个键值,它会查询数组中所有的对象来查找这个键值,然后将查询的结果打包到另一个数组中返回;

例:假设book中有个NSArray数组 相关书籍(relativeBooks)属性,现在想获取所有相关书籍的名称(reBookName)(只是讲解问题,不考虑实际意义)

  1. <span style="white-space:pre">  </span>Book *book = [[Book alloc] init];  
  2.     NSArray *reBooks = [NSArray arrayWithObjects:reBook1,reBook2,reBook3,nil];  
  3.     [book setValue:reBooks forKey:@"relativeBooks"];  
  4.     NSArray *bookNames = [book valueForKeyPath:@"relativeBooks.reBookName"];//获取到所有的相关书籍对象的reBookName  

 

 

4.KVC的简单运算:

kvc还可以做一些简单的运算,如:求和(sum),最大值最小值(max   min),平均值(avg),个数(count)

用法:在以上关键字前加上@符号即可,然后加在你所求的属性前

例:求上面所有相关书籍的个数,总价格,最高价,最低价,平均价

 

 
  1. Book *book = [[Book alloc] init];  
  2. [book valueForKeyPath:@"relativeBooks.@count"];//个数  
  3. [book valueForKeyPath:@"relativaBooks.@max.price"];//在price前加上@max求relativaBooks中price最大值,并返回最大值  
  4. [book valueForKeyPath:@"relativaBooks.@min.price"];//最小值  
  5. [book valueForKeyPath:@"relativaBooks.@avg.price"];//平均值  
  6. [book valueForKeyPath:@"relativaBooks.@sum.price"];//求和  

 

KVO的基本概念:kvo使用了观察者模式,当被观察对象的属性发生变化时会通知观察者;

使用:kvo的使用简单的分为三步

1.注册观察者 2.实现回调方法(当被观察的属性发生变化时会回调此方法)3.移除观察者

实例:现在我们要观察Book对象的name属性(以下为伪代码,只为讲解知识点)

 

 
  1. 1.创建一个Book对象  
  2. @interface Book : NSObject{  
  3.     NSString * name;  
  4.     int         price;  
  5. }  
  6. @end  
  7. 2.假设现在要在一个Controller中观察Book对象中的name属性  
  8. 注册观察者:你要观察哪个对象中的属性就用哪个对象注册观察者(如下面方法要观察Book中的name就用book调用addObserver方法),observer:参数是你在什么对象中实现回调,此处我们在self中实现回调,forKeyPath中是要观察的属性名称(如观察name属性就填入name,此处支持kvc中提到的路径),options中填的是你想把name的旧值传到回调方法中,还是传新值,或新旧值都传  
  9. Book *book =  [[Book alloc] init];   
  10. [book addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];   
  11. 3.实现回调   
  12. 方法的object参数就是观察的对象,此处是Book对象 ;change中能拿到修改前后的新旧数据(这要看注册观察者时传的是新值还是旧值,还是新旧都传)  
  13. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(voidvoid *)context  
  14. {  
  15.     if([keyPath isEqualToString:@"name"])  //判断被观察的属性  
  16.     {  
  17.         myLabel.text = [stockForKVO valueForKey:@"price"];  
  18.     }  
  19. }  
  20. 4.取消观察  
  21. [book removeObserver:self forKeyPath:@"name"];  



 

注意:如果需要实现kvo,必须调用kvc的setValueForKey方法,或对象属性的set方法(如book.name = @"aaaa")来改变被观察对象的属性,才能触发kvo的回调方法

如果在Book对象直接修改(如name=@"changeName"),没有调用其set方法是不会触发kvo回调的

备注:以上为本人浅见,如有不对,希望各位大大们指出纠正,谢谢!!

posted on 2015-12-03 17:21  没有14  阅读(82)  评论(0)    收藏  举报

导航