zoukankan      html  css  js  c++  java
  • KVC 开发详情

    目录

    • 概述

    • 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<Key>
    -(NSUInteger)countOfArray{
        return 3;
    }
    // -(id)objectIn<Key>AtIndex:(NSInteger)index
    -(id)objectInArrayAtIndex:(NSInteger)index{
        NSArray * otherData = @[@"A1",@"B1",@"C1"];
        return [otherData objectAtIndex:index];
    }
    // -(NSArray *)<key>AtIndexes:(NSIndexSet *)indexes
    -(NSArray *)arrayAtIndexes:(NSIndexSet *)indexes{
        NSArray * otherData = @[@"A2",@"B2",@"C2"];
        NSArray * result = [otherData objectsAtIndexes:indexes];
        return result;
    }
    // -(void)get<Key>:(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<Key>
    -(NSUInteger)countOfTestSet{
        return 3;
    }
    // -(NSEnumerator *)enumeratorOf<Key>
    -(NSEnumerator *)enumeratorOfTestSet{
        NSSet * set = [NSSet setWithArray:@[@"set1",@"set2",@"set3"]];
        return [set objectEnumerator];
    }
    // 只检验 ,不调用
    // -(NSSet *)memberOf<Key>:(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"]);
    

      

  • 相关阅读:
    10个你可能不知道的JavaScript小技巧
    QuickFlow2.0 安装指南
    QuickFlow教程(5): RuleDriven活动,角色提供程序自定义,邮件模板
    QuickFlowDesigner教程(2)工作流表单快速自定义
    QuickFlowDesigner1.0(Build091025)发布
    QuickFlow2.0无代码工作流设计器QuickFlowDesigner1.0 beta publish
    QuickFlowDesigner教程(3)UI代码和工作流交互
    QuickFlow Aspx Form example deploy wizard
    多选用户字段的Caml查询问题
    QuickFlowDesigner教程(4)如何用代码控制活动操作人
  • 原文地址:https://www.cnblogs.com/shuigu/p/6351296.html
Copyright © 2011-2022 走看看