博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
KVC 开发详情
阅读量:5825 次
发布时间:2019-06-18

本文共 5289 字,大约阅读时间需要 17 分钟。

目录

  • 概述

  • KVC基本技术

  • KVC访问函数

  • KVC搜索顺序

  • KVC集合操作

一、概述

  kvc全名是Key-value coding,kvc是一种通过字符串间接的访问oc对象的属性的一种技术。

  一个oc对象之所以能使用kvc技术,是因为NSObject已经实现了NSKeyValueCoding协议,所以继承NSObject类都能用kvc技术。

  访问函数是指访问oc对象的属性的函数,一般分为setter、getter两种。  

二、KVC基本技术

  前面说过kvc是间接访问oc对象的属性的一种技术,是通过下面4个函数来实现的

  1.setValue:forKey

  2.valueForKey:

  3.setValue:forKeyPath

  4.valueForKeyPath:

  我们可以通过这个例子来了解这4个函数

  假设一个人person养有一只猫cat,这只cat有一个名字name.

  如果要给这个猫改名,可以这样写

[cat setValue:@"猫星人" forKey:@"name"];

  可以这样读取这个猫的名字

NSString * name = [cat valueForKey@"name"];

  当然也可以通过 "那个人" 改那只猫的名字或者读取,这时我们的KeyPath就出场了

[person setValue:@"猫星人" forKeyPath:@"cat.name"];NSString * name = [person valueForKeyPath:@"cat.name"];

三、KVC访问函数

  访问函数分为getter、setter。当调用valueForKey:的时候会调用getter函数,当调用setValue:forKey的时候会调用setter函数。OC会为@property属性自动添加getter、setter。

  getter函数如下

// name的getter函数-(NSString *)name{   return @"";  }// 如果是bool类型的话还可以这样-(BOLL)isHidden{   return YES;        }

  setter函数

-(void)setName:(NSString *)name{    _name = name;}  

  值得注意的时Array、MutableArray、Set、MutableSet 的getter函数,它们的getter函数不是一个,而是一套。

  Array的getter函数有下面4个构成

// -(NSUInteger)countOf
-(NSUInteger)countOfArray{ return 3;}// -(id)objectIn
AtIndex:(NSInteger)index-(id)objectInArrayAtIndex:(NSInteger)index{ NSArray * otherData = @[@"A1",@"B1",@"C1"]; return [otherData objectAtIndex:index];}// -(NSArray *)
AtIndexes:(NSIndexSet *)indexes-(NSArray *)arrayAtIndexes:(NSIndexSet *)indexes{ NSArray * otherData = @[@"A2",@"B2",@"C2"]; NSArray * result = [otherData objectsAtIndexes:indexes]; return result;}// -(void)get
:(NSString **)buffer range:(NSRange)inRange-(void)getArray:(NSString **)buffer range:(NSRange)inRange{ NSArray * otherData = @[@"A3",@"B3",@"C3"]; for (NSUInteger i=inRange.location; i < inRange.length; i++) { *(buffer+i)= [otherData objectAtIndex:i]; }}

   set的getter函数

// -(NSUInteger)countOf
-(NSUInteger)countOfTestSet{ return 3;}// -(NSEnumerator *)enumeratorOf
-(NSEnumerator *)enumeratorOfTestSet{ NSSet * set = [NSSet setWithArray:@[@"set1",@"set2",@"set3"]]; return [set objectEnumerator];}// 只检验 ,不调用// -(NSSet *)memberOf
:(NSSet *)object{
-(NSSet *)memberOfTestSet:(NSSet *)object{ return nil;}

  mutableArray的getter函数,假设key为testMArray.

-(void)insertObject:(NSString *)object inTestMArrayAtIndex:(NSUInteger)index{    [testMArray insertObject:object atIndex:index];}-(void)removeObjectFromTestMArrayAtIndex:(NSUInteger)index{    [testMArray removeObjectAtIndex:index];}-(void)insertTestMArray:(NSArray *)array atIndexes:(NSIndexSet *)indexes{    [testMArray insertObjects:array atIndexes:indexes];}-(void)removeTestMArrayAtIndexes:(NSIndexSet *)indexes{    [testMArray removeObjectsAtIndexes:indexes];}-(void)setTestMArray:(NSMutableArray *)array{//    [testMArray setArray:array];}

  

四、KVC搜索顺序

  当调用setValue:forKey、valueForKey:,系统并不是简单的调用getter、setter函数,而是有一套流程顺序。

  setter 函数模板: [set<Key>:]

  getter 函数模板: [_<key>,<key>,get<Key>,_is<Key>,is<Key>]  

  setter的搜索过程比较简单,如下:  

    1.搜索 set<Key>:函数,找到直接调用

    2.如果1找不到,就搜索[_<key>,<key>,_is<Key>,is<Key>]成员变量,找到直接访问成员变量( 类函数accessInstanceVariablesDirectly需要返回YES,默认就是返回YES )  

    3.如果需要就调用setNilValueForKey:

    4.1、2、3 都没有命中就调用 setValue:forUndefinedKey:

  getter的搜索过程

    1.搜索 get<Key>, <key>, is<Key> 函数,找到就直接调用,

    2.如果1找不到,就搜索如下组合 A:[countOf<Key> ,objectIn<Key>AtIndex:]、B:[countOf<Key>,<key>AtIndexes: ] ,如果找到A,B其中一个组合就通过这个组合,返回一个NSArray给 valueForKey:,如果A,B都存在,就以B为准。在A、B存在的情况下 可以实现get<Key>:range: 函数最后修改将要返回的数组。

    3.如果2找不到,就搜索下面三个函数 [countOf<Key>、enumeratorOf<Key>、memberOf<Key>:],如果这三个函数都找到就通过enumeratorOf<Key>返回一个NSSet对象。memberOf<Key>:]只用于检测,不调用?

 

    4.如果3还没用命中,就搜索 _<key>, _is<Key>, <key>, is<Key> 实例变量,找到就直接访问( 类函数accessInstanceVariablesDirectly需要返回YES,默认就是返回YES )

    5.如果1、2、3、4都没有命中 就调用valueForUndefinedKey:

    

    [objc mutableArrayValueForKey:key] 与 [objc valueForKey:] 类似,但是前者返回的是一个特殊的proxy mutableArray。

    1. A :[insertObject:in<Key>AtIndex:,removeObjectFrom<Key>AtIndex:]
      B :[insert<Key>:atIndexes:,remove<Key>AtIndexes:]
      C :[replaceObjectIn<Key>AtIndex:withObject: ,replace<Key>AtIndexes:with<Key>: ]
      至少实现[一个insert,一个remove]时,当给proxy发送insert movie 消息时,会调用A,或者B的方法,不会给原mutableArray发送消息。
    2.如果A,B都没有实现,就搜索set<Key>:,有就调用(不推荐用)
    3.搜索 _<key> , <key>,搜索到就直接用成员变量
    4.如果3搜索不到就报NSUndefinedKeyException

五、KVC集合操作

  kvc的集合操作是指:当被操作的对象是集合(Array)时可以通过valueForKeyPath函数返回一个被处理过的子集。

  有如下处理行为

  1. max - 集合的最大值
  2. min - 集合的最小值
  3. agv - 集合的平均值
  4. count - 集合的个数
  5. sum - 集合的总数

  概念方面已经没有什么可以介绍的了,我们直接看代码  

self.scores = @[                 @{@"name":@"A",@"score":@90},                 @{@"name":@"B",@"score":@88},                 @{@"name":@"C",@"score":@92},                 @{@"name":@"D",@"score":@92},                 ];// 只是代码// 个数 NSLog(@"scores count = %@",[self.scores valueForKeyPath:@"@count"]); NSLog(@"scores avg   = %@",[self.scores valueForKeyPath:@"@avg.score.intValue"]); NSLog(@"scores max   = %@",[self.scores valueForKeyPath:@"@max.score"]); NSLog(@"scores min   = %@",[self.scores valueForKeyPath:@"@min.score.intValue"]); NSLog(@"scores sum   = %@",[self.scores valueForKeyPath:@"@sum.score.intValue"]);

  

 

转载于:https://www.cnblogs.com/shuigu/p/6351296.html

你可能感兴趣的文章
软件工程师成长为架构师必备的十项技能
查看>>
python 异常
查看>>
百度账号注销
查看>>
mysql-This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME 错误解决
查看>>
BIEE Demo(RPD创建 + 分析 +仪表盘 )
查看>>
Cocos2dx 3.0开发环境的搭建--Eclipse建立在Android工程
查看>>
基本概念复习
查看>>
重构第10天:提取方法(Extract Method)
查看>>
Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
查看>>
解决pycharm在ubuntu下搜狗输入法一直固定在左下角的问题
查看>>
多线程day01
查看>>
react-native 模仿原生 实现下拉刷新/上拉加载更多(RefreshListView)
查看>>
MySQL出现Access denied for user ‘root’@’localhost’ (using password:YES)
查看>>
通过Roslyn构建自己的C#脚本(更新版)(转)
查看>>
红黑树
查看>>
UIImagePickerController拍照与摄像
查看>>
python调用windows api
查看>>
第四章 mybatis批量insert
查看>>
Java并发框架——什么是AQS框架
查看>>
【数据库】
查看>>