• KVC


    KVC 为核心方法,闭源,没有源码,只能猜测。为了方便理解,自己根据官方文档的描述,实现了一个简单的KVC,所以是不安全的,只作为理解学习使用。(在导入第三方框架的时候,需要考虑是否有导入的必要性,权衡利弊)

     

    KVC官方文档

    https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple_ref/doc/uid/10000107i

     

    Key-value coding is a mechanism enabled by the NSKeyValueCoding informal protocol that objects adopt to provide indirect access to their properties.

    翻译:KVC是对象提供的一种可以通过NSKeyValueCoding协议便捷的间接访问属性机制。

     

    需要理解的内容:

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

    全部为成员变量

    实例变量是一宗特殊的成员变量

    @interface KVCViewController (){

        @public

        NSString *myName; //成员

        UIButton *btn; //实例变量

        id hell; //id 是一种特殊的 class 所以也是实例变量

    }

    属性系统会生成默认的setter + getter

    GCC -> LLVM(编译器升级)

    LLVM为没有匹配的实例变量属性,自动创建一个带下划线的成员变量

    @sythesie namep = _namep; //自动生成setter getter 

     

     

    官方文档讲到KVC分为简单类型(但是并没有讲简单类型包括哪些,个人认为是int,number,string...)和复杂类型(array, set):

     

    简单类型 --------------------------------------------------

    setValue forKey流程:

    查找调用顺序 set<Key>, _set<Key> 如果没有实现以上两个方法并且+ (BOOL)accessInstanceVariablesDirectly(返回NO崩溃)  返回YES --> 那么就会依次按 _<key>_is<Key><key>, or is<Key> 顺序查找成员变量并且赋值。 

     

    valueForKey查找流程:

    查找调用顺序 get<Key>, <key>, is<Key>, or _<key> 下面是官方文档截图(很详细):

    在使用value forkey过程中,经过自己验证发现以下查找逻辑(如果是简单的实例变量):

    总的查找顺序是 get<Key>, <key>, is<Key>, or _<key>

    1. 如果当前属性自动生成set get方法则系统会按照get<Key>, <key>顺序查找方法是否实现,不会查找后面is<Key>, <key>方法。

    2. 如果当前是成员变量,则还是会按照get<Key>, <key>, is<Key>, or _<key>顺序查找调用(只调用其中一个方法)。 

    3. 如果四个方法都没实现并且+ (BOOL)accessInstanceVariablesDirectly(默认返回Yes) 返回NO系统崩溃,返回YES不会崩溃,值为null。

     

    复杂实例变量:

    NSArray->走第2步

    NSSet(哈希,散列表)->走第3部。

     

    代码:

     

    #import "Person.h"

     

    @implementation Person

    #pragma mark - set相关

    - (void)setName:(NSString *)name{

        NSLog(@"%s",__func__);

    }

    - (void)_setName:(NSString *)name{

        NSLog(@"%s",__func__);

    }

    - (void)setIsName:(NSString *)isName{

        NSLog(@"%s",__func__);

    }

     

    #pragma mark - get相关

    - (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);

    }

     

    #pragma mark - 关闭或开启实例变量赋值

    //是否开启间接访问变量

    + (BOOL)accessInstanceVariablesDirectly{

        return NO;

    }

    @end

     

     

     


    复杂类型 --------------------------------------------------

    数组:验证valueForKey发现以下逻辑

    NSArray *arr = [p valueForKey:@"fxArray"]; // 动态成员变量

    [arr containsObject:@"fxArray 0"];

    //数组valueForKey 与 contaainsObject 都会会调用以下方法:

    // 个数

    - (NSUInteger)countOfFxArray {

        return [self.array count];

    }

     

    //// 获取值

    - (id) objectInFxArrayAtIndex:(NSUInteger)index {

        return [NSString stringWithFormat:@"fxArray %lu", index];

    }

     

     

    集合

     

    demo: https://github.com/531837586/fxDemo

     

     

     

     

     

     

  • 相关阅读:
    Spring/Java error: namespace element 'annotation-config' … on JDK 1.5 and higher
    警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:Zhuo' did not find a matching property.
    快速学习Symfony4,Symfony4教程
    window下安装redis报错: creating server tcp listening socket 127.0.0.1:6379: bind No error
    Windows 安装nginx
    js焦点事件:onfocus、onblur、focus()、blur()、select()
    input 输入框只能输入纯数字
    随机抽取不重复的数组元素
    常用 书签 mark 常用网站
    仿真灯泡 电灯泡 灯光 光环闪烁 流星雨
  • 原文地址:https://www.cnblogs.com/coolcold/p/12027653.html
Copyright © 2020-2023  润新知