美文网首页
KVC 相关

KVC 相关

作者: user_bo | 来源:发表于2018-12-03 16:13 被阅读0次
    • 1 .KVC 的基本使用
      kvc 相关的基本方法包括

    设置属性值:::
    setValue: forKey: ;
    setValue: forKeyPath: ;
    获取属性值:::
    valueForKey: ;
    valueForKeyPath: ;

    keyPath 是指可以多层通过路径设置属性 或者获取属性值

    @interface Dog : NSObject
    {// 这里的成员变量没有 set/ get 方法
        @public
        int dog_age; // 一般成员变量
        NSString * dog_food; // 实例变量
    }
    @property (nonatomic,copy)NSString * dog_name ; // 属性
    @end
    
    @interface Person : NSObject
    {
        @public
        int person_age;
        NSString * person_food;
    }
    @property (nonatomic,copy)NSString * person_name;
    
    @property (nonatomic,strong)Dog * dog;
    @end
    
    // -------------------vc 中调用
       self.person = [Person new];
       
        [self.person setValue:@"jack" forKey:@"person_name"];
        [self.person setValue:@"三明治" forKey:@"person_food"];
        [self.person setValue:@12 forKey:@"person_age"];
    
        NSLog(@"person name value is :: %@",[self.person valueForKey:@"person_name"]);
        NSLog(@"person name is :: %@",self.person.person_name);
       
        NSLog(@"person food value is :: %@",[self.person valueForKey:@"person_food"]);
        NSLog(@"person food is :: %@",self.person->person_food);
      
        NSLog(@"person age value is :: %@",[self.person valueForKey:@"person_age"]);
        NSLog(@"person age is :: %d",self.person->person_age);
        
        self.person.dog = [Dog new];
       
        [self.person setValue:@"pretty" forKeyPath:@"dog.dog_name"];
        [self.person setValue:@"狗粮" forKeyPath:@"dog.dog_food"];
        [self.person setValue:@2 forKeyPath:@"dog.dog_age"];
    
        NSLog(@"person dog name value is :: %@",[self.person valueForKeyPath:@"dog.dog_name"]);
        NSLog(@"person dog name is :: %@",self.person.dog.dog_name);
    
        NSLog(@"person dog food value is :: %@",[self.person valueForKeyPath:@"dog.dog_food"]);
        NSLog(@"person dog food is :: %@",self.person.dog->dog_food);
    
        NSLog(@"person age value is :: %@",[self.person valueForKeyPath:@"dog.dog_age"]);
        NSLog(@"person dog age is :: %d",self.person.dog->dog_age);
    
    /*
    key::
    person name value is :: jack
    person name is :: jack
    person food value is :: 三明治
    person food is :: 三明治
    person age value is :: 12
    person age is :: 12
    
    keyPath::
    person dog name value is :: pretty
    person dog name is :: pretty
    person dog food value is :: 狗粮
    person dog food is :: 狗粮
    person age value is :: 2
    person dog age is :: 2
    */
    

    通过代码验证可以得到相关的结果:: kvc 通过key /keypath 设置成员变量得值

    • 2 .kvc的调用顺序
      赋值过程:


      KVC调用顺序.png

    ** 1 . 是否包含 setKey: 、 _setKey:的方法
    (包含:传参 赋值 ; 不包含 -> 2);

    ** 2 . 通过判断 + (BOOL)accessInstanceVariablesDirectly 的值(是否可以直接访问实例变量 ,默认值 true)
    (ture:查找相关成员变量 -> 3 ; false -> 报错 ::undefined key);

    ** 3 . 成员变量得查找顺序 _key , _isKey , key , isKey
    (发现变量:传参 赋值 ; 未发现变量 -> 报错 ::undefined key);

    取值过程:


    kvc取值.png

    //

    • 3 . kvc 是否调用kvo???
      解答::(kvc修改 成员变量 、属性 都会调用kvo)
    @interface Person : NSObject
    {
        @public
        int person_age;
    }
    @property (nonatomic,copy)NSString * person_name;
    @end
    
    //________________________ VC 调用
    
    @interface ViewController ()
    
    @property (nonatomic,strong)Person *person;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.person = [Person new];
        // 设置初始值
        [self.person setValue:@"jack" forKey:@"person_name"];
        [self.person setValue:@12 forKey:@"person_age"];
        
    // 添加监听 name age
        [self.person addObserver:self forKeyPath:@"person_name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"name"];
        [self.person addObserver:self forKeyPath:@"person_age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"age"];
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    // 修改成员变量 、 属性的值
        [self.person setValue:@"rose" forKey:@"person_name"];
        [self.person setValue:@13 forKey:@"person_age"];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        NSLog(@"keyPath:: %@ ; object:: %@ ; change :: %@ ; context :: %@ ",keyPath,object,change,context);
    }
    
    - (void)dealloc
    {
        [self.person removeObserver:self forKeyPath:@"person_age"];
        [self.person removeObserver:self forKeyPath:@"person_name"];
    }
    @end
    /*
    // kvo:: name 
    keyPath:: person_name ; object:: <Person: 0x60000371c3c0> ; change :: {
        kind = 1;
        new = rose;
        old = jack;
    } ; context :: name
    
     kvo:: age
    keyPath:: person_age ; object:: <Person: 0x60000371c3c0> ; change :: {
        kind = 1;
        new = 13;
        old = 12;
    } ; context :: age
    */
    

    这里可以推断一个结论 :
    kvo的实现依赖于方法 ::willChangeValueForKey 、didChangeValueForKey
    推断 kvc 修改值得时候调用顺序::

    1 . willChangeValueForKey
    2 . 根据前面讲到的查找顺序修改 value
    3 . didChangeValueForKey

    相关文章

      网友评论

          本文标题:KVC 相关

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