美文网首页
iOS底层原理之`OC语法`(二.KVC和KVO)

iOS底层原理之`OC语法`(二.KVC和KVO)

作者: Coder_Cat | 来源:发表于2018-08-17 00:43 被阅读4次

    1. KVC

    • KVC的全称是Key-Value Coding,俗称“键值编码”,可以通过一个key来访问某个属性。
    • 常见的API有:
    - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;//通过keyPath可以设置属性的属性
    - (void)setValue:(id)value forKey:(NSString *)key;//通过key设置自己的属性
    - (id)valueForKeyPath:(NSString *)keyPath;//通过keyPath访问属性的属性
    - (id)valueForKey:(NSString *)key; //通过key访问自己的属性
    
    • kvc设置属性原理:


      kvc设置属性原理
    • setValue:forKey的原理详解:

      1. 先去寻找setKey:方法(即对应key的set方法),找到了就去传递参数调用方法;
      2. 如果没找到,再去寻找_setKey:的方法,找到可传值;
      3. 没找到就去查看+ (BOOL)accessInstanceVariablesDirectly;这个方法是不是设置为YES(默认是YES),如果设置的是YES这表示直可以接访问实例成员变量;
      4. 然后会去查看有没有_key的成员变量、有就设值;
      5. 没有就去查看有没有_isKey的成员变量、有就设值;
      6. 没有就去查看有没有key的成员变量、有就设值;
      7. 没有就去查看有没有isKey的成员变量、有就设值;
      8. 如果还没找到就会抛异常:NSUnknownKeyException
      9. 如果上面accessInstanceVariablesDirectly设置为NO,并且setKey:、_setKey:这两个set方法没找到就会抛异常,不会去访问属性。
        示例1:
    @interface Person : NSObject{
    @public
    //    int _age;
        int _isAge;
        int age;
        int isAge;
    
    }
    
    /**age属性*/
    //@property(nonatomic,assign) int age;
    @end
    
    @implementation Person
    
    //-(void)setAge:(int)age{
    //    _age = age;
    //}
    //-(void)_setAge:(int)age{
    //    _age = age;
    //}
    @end
    
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Person * p = [[Person alloc]init];
            [p setValue:@18 forKey:@"age"];
    //      NSLog(@"%d",p->age);
            
        }
        return 0;
    }
    
    
    kvc设置属性原理

    上面代码和调试结果可以看出:当把两个set方法和_age成员变量注销后会优先访问_isAge成员变量,可以通过注销其他的成员变量一次证明方法的顺序,这里不再赘述。

    在Person类中重写+ (BOOL)accessInstanceVariablesDirectly;方法,并设置返回值为NO,编译就会抛异常。

    @implementation Person
    + (BOOL)accessInstanceVariablesDirectly{
        return NO;
    }
    @end
    
    抛异常.png
    • kvc取值原理:


      kvc取值原理.png
    • valueForKey:原理详解:
    1. 同设置属性一样,取值时访问方法的顺序是getKeykeyisKey_key,找到前面的方法就调用给成员变量取值就不会再往下找了。
    2. 如果上面的方法都没找到就会去查看accessInstanceVariablesDirectly`这个方法是不是设置为YES,如果设置的是YES这表示直可以接访问实例成员变量;
    3. 设置成员变量的顺序为:_key_isKeykeyiskey找到前面的成员变量取值就不会再往下找了;
    4. 如果没有找到上面的成员变量,就会抛异常:NSUnknownKeyException
    5. 如果上面accessInstanceVariablesDirectly设置为NO,并且上面的方法都没有找到也会抛异常。
    • 注意:上面的赋值取值方法以及成员变量可以是私有的,依然可以访问,即KVC是可以访问对象的私有属性的。
    //.m文件
    #import "Person.h"
    @interface Person(){
        @private
        int _age;
        int _isAge;
        int age;
        int isAge;
    }
    
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            Person * p = [[Person alloc]init];
            [p setValue:@18 forKey:@"age"];
            NSLog(@"%@",[p valueForKey:@"age"]);
            
        }
        return 0;
    }
    
    kvc访问私有属性.png

    相关文章

      网友评论

          本文标题:iOS底层原理之`OC语法`(二.KVC和KVO)

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