美文网首页
iOS-KVC相关

iOS-KVC相关

作者: 漆黑烈焰武士G | 来源:发表于2019-07-28 17:30 被阅读0次

    KVC相关


    一、 iOS成员变量,实例变量,属性变量的区别

    @interface Person : NSObject
    {
      @public
        NSString *name;
        id object;  // id是一种特殊的Class,是OC特有的OC对象
        UIButton *btn;// 实例变量--由Class进行实例化而生成的对象为实例变量
        int age;
    }// 大括号内均为成员变量
     // 实例变量是一种特殊的成员变量
    
    // 属性 有默认的 setter 和 getter 方法
    // 当 LLVM 发现一个属性 没有匹配的  成员变量 时,会生成getter&setter方法并创建一个下划线的成员变量
    //  property自动生成的setter和getter方法都会自动生成_<key>的变量,如果只重写setter或getter中的一个,另一个还是会生成下划线变量,但是同时重写setter和getter的话就无法自动生成下划线变量了
    @property (nonatomic, copy) NSString *name2;
    @property (nonatomic, strong) Son *son;
    
    - (void)walk;
    + (void)study;
    
    @end
    

    二、KVC取值、赋值原理

    *学习方式:
    1、分析源码 - 没有开源

    ​ 2、官方文档:Key-Value Coding Programming Guide


    KVC是什么

    Key-Value是一种通过NSKeyValueCoding协议间接访问成员变量的机制

    KVC有什么作用

    键值编码

    - (void)viewDidLoad
    {
      [super viewDidLoad];
      Person *p = [Person new];
      Son *s = [Son new];
      [p setValue:s forKeyPath:@"son"];
      [p setValue:@"hehe" forkey:@"name2"];
      [p setValue:@"didi" forKeyPath:@"son.subject_Son"];
    }
    
    KVC的原理是什么
    赋值过程 setValue:forKey

    1、先查找set<key>,_set<Key>方法,若存在则不走“2、”

    2、若没有上述方法且accessInstanceVariablesDirectly==YES,则先存在_<Key>,_is<Key>,<Key>,is<Key>

    *上述情况均只执行一次

    .h
    @interface Person : NSObject{
        @public
        NSString *name; 
        NSString *_name; 
        NSString *_isName;
        NSString *isName;
    }
    
    .m
        //此时Person类中没有set<key>,_set<Key>方法
            Person *p = [[Person alloc] init];
        [p setValue:@"hehe" forKey:@"name"];
        
        NSLog(@"p->isName:%@",p->isName);
        NSLog(@"p->name:%@ - p->isName:%@",p->name,p->isName);
        NSLog(@"p->name:%@ - p->isName:%@ - p->_isName:%@",p->name,p->isName,p->_isName);
        NSLog(@"p->name:%@ - p->isName:%@ - p->_name:%@ - p->_isName:%@",
              p->name,p->isName,p->_name,p->_isName);
    
    输出:
     p->isName:(null)
     p->name:(null) - p->isName:(null)
     p->name:(null) - p->isName:(null) - p->_isName:(null)
     p->name:(null) - p->isName:(null) - p->_name:hehe - p->_isName:(null)
    
    取值过程 valueForKey:

    1、普通类型

    //如果重写了这些方法,则会调用重写的方法,按从上到下的顺序,只调一次
    - (NSString *)getName
    {
        NSLog(@"%s",__func__);
        return NSStringFromSelector(_cmd);
    }
    - (NSString *)name
    {
        NSLog(@"%s",__func__);
        return NSStringFromSelector(_cmd);
    }
    - (NSString *)isName
    {
        NSLog(@"%s",__func__);
        return NSStringFromSelector(_cmd);
    }
    - (NSString *)_name
    {
        NSLog(@"%s",__func__);
        return NSStringFromSelector(_cmd);
    }
    

    2、集合类型:array、set

    3、如没有一系列的getter方法,需将accessInstanceVariablesDirectly(是否开启间接访问) 设为为 YES(默认值也是YES)时,访问顺序为:

    _<key>,_is<key>,<key>,is<key>

    .h  
    @interface Person : NSObject{
        @public
        NSString *name; 
        //NSString *_name; 
        NSString *_isName;
        NSString *isName;
    }
    
    .m
            Person *p = [[Person alloc] init];
          [p setValue:@"hehe" forKey:@"name"];
        //p->_name   = @"_name";
        p->_isName = @"_isName"; // MAP -- KEY - VALUE
        p->name    = @"name";
        p->isName  = @"isName";
            NSLog(@"%@",[p valueForKey:@"name"]); // 方法 getName
    输出:
        //_name
        _isName
    

    *解释:

    ​ 在赋值时,若set<key>,_set<Key>不存在,但name,_name,_isName,isName都存在,则 [p setValue:@"hehe" forKey:@"name"]实际上是将hehe赋值在_name中,并且不存在其他属性中,若_name不存在则赋值在_isName中。

    ​ 所以取值时,存的时候存在哪就在哪取,不然取不到。


    相关文章

      网友评论

          本文标题:iOS-KVC相关

          本文链接:https://www.haomeiwen.com/subject/gueprctx.html