zoukankan      html  css  js  c++  java
  • KVC/KVO 本质

    KVO 的实现原理

    1. KVO是关于runtime机制实现的

    2. 当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制

    3. 如果原类为Person,那么生成的派生类名为NSKVONotifying_Person

    4. 每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统就会偷偷讲isa指针指向动态生成的派生类,从而在给被监控属性复制是执行的是派生类的setter方法

    5. 键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:和didChangeValueForKey:,在一个被观察属性发生改变之前,willChangeValueForkey:和didChangeValueForKey:;在一个被观察属性发生改变之前,willChangeValueForKey:一定会被调用,这就会记录旧的值。而当改变发生后,didChangeValueForKey:会被调用,继而observeValueForKey:ofObject:change:context:也会被调用

    举例伪代码_NSSet*ValueAndNotify
    
    - (void)setAge:(int)age
    {
        _NSSetIntValueAndNotify();
    }
    
    // 伪代码
    void _NSSetIntValueAndNotify()
    {
        [self willChangeValueForKey:@"age"];
        [super setAge:age];
        [self didChangeValueForKey:@"age"];
    }
    
    - (void)didChangeValueForKey:(NSString *)key
    {
        // 通知监听器,某某属性值发生了改变
        [oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
    }
    
    

    KVC的实现原理

    • KVC是Key Value Coding的简称。它是一种可以通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。KVC的方法定义在Foundation/NSKeyValueCoding中。

    KVC使用的基本方法:

    - (void)setValue:(nullableid)value forKey:(NSString*)key;//通过Key来设值
    - (void)setValue:(nullableid)value forKeyPath:(NSString*)keyPath;//通过KeyPath来设值
    - (nullableid)valueForKey:(NSString*)key;//直接通过Key来取值
    - (nullableid)valueForKeyPath:(NSString*)keyPath;//通过KeyPath来取值
    

    KVC 赋值 setValue:forKey:

    1. setValue:forKey:将键字符串key所对应的属性的值设置为value。(按照setKey:、_setKey:顺序查找方法)如果没有找到Set方法的话,将调用方法setValue:ForUndefinedKey:。并抛出异常 NSUnknowKeyException

    2. 若没有找到Set方法,会调用对象的类方法+ (BOOL)accessInstanceVariablesDirectly;此方法返回YES时(默认返回YES),会按照_key,_iskey,key,iskey的顺序搜索成员,然后赋值。

    3.  若都没找到成员变量,将调用方法setValue:ForUndefinedKey:。并抛出异常 NSUnknowKeyException

    KVC 取值值 valueForKey:

    1. 按先后顺序搜索getKey:、key、isKey、三个方法,若某一个方法被实现,取到的即是方法返回的值,后面的方法不再运行。如果是BOOL或者Int等值类型, 会将其包装成一个NSNumber对象。

    2. 若这三个方法都没有找到,则会调用+ (BOOL)accessInstanceVariablesDirectly方法判断是否允许取成员变量的值。若返回NO,直接调用- (nullable id)valueForUndefinedKey:(NSString *)key方法,并抛出异常 NSUnknowKeyException

    3. 若返回YES,会按先后顺序取_key、_isKey、 key、isKey成员变量的值。调用- (nullable id)valueForUndefinedKey:(NSString *)key方法。

    补充

    1. KVC提供属性值正确性验证的API,它可以用来检查set的值是否正确、为不正确的值做一个替换值或者拒绝设置新值并返回错误原因。
    - - (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
    
    1. KVC中的异常.获取值时找不到key- (nullable id)valueForUndefinedKey:(NSString *)key;

    2. 设值时找不到key- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;

    3. 给不能设置nil的属性设置了nil。

    • 如果你在SetValue方法时面给Value传nil,则会调用这个方法
    • (void)setNilValueForKey:(NSString *)key;
  • 相关阅读:
    Divide Two Integers
    LRU Cache
    Max Points on a Line
    Recover Binary Search Tree
    Copy List with Random Pointer
    IEE修改最大连接数
    SQL Tuning 基础概述02
    RHEL 本地yum源配置
    Linux演示 dd测试IO
    Linux平台oracle 11g单实例 安装部署配置 快速参考
  • 原文地址:https://www.cnblogs.com/ShaoYinling/p/10238492.html
Copyright © 2011-2022 走看看