美文网首页
KVC知识点

KVC知识点

作者: ychen3022 | 来源:发表于2018-10-04 15:47 被阅读5次
    1、KVC简介

    KVC的全称是Key-Value Coding,俗称“键值编码”,可以通过一个key来访问某个属性

    常见的API有:
    //设置属性值
    - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
    - (void)setValue:(id)value forKey:(NSString *)key;
    //获取属性值
    - (id)valueForKeyPath:(NSString *)keyPath;
    - (id)valueForKey:(NSString *)key; 
    
    2、探究KVC本质

    创建文件MJPerson.h

    #import <Foundation/Foundation.h>
    
    @interface MJPeroson : NSObject
    //1.这样直接定义变量,在没有set、get方法的时候,会按照_age、_isAge、age、isAge的方法去查找成员变量
    {
        int _age;
        int _isAge;
        int age;
        int isAge;
    }
    
    //2.这种定义属性,会自动生成对应的set方法和get方法
    //@property(nonatomic,assign) int age;
    
    @end
    

    创建文件MJPerson.m

    #import "MJPeroson.h"
    
    @implementation MJPeroson
    
    -(void)setAge:(int)age{
      //  _age = age;//这句代码不写,值不会改变,但是依然会触发KVO
        NSLog(@"执行setAge方法");
    }
    
    -(void)_setAge:(int)age{
    //  _age = age;//这句代码不写,值不会改变,但是依然会触发KVO
        NSLog(@"执行_setAge方法");
    }
    
    +(BOOL)accessInstanceVariablesDirectly{
        //这个类方法是默认YES,在MJPerson类alloc的时候会执行
        //返回NO表示,不允许直接访问成员变量,接抛出异常
        //返回YES表示,允许直接访问成员变量,按照_age、_isAge、age、isAge的顺序去访问成员变量,如果以上四个成员变量都没有的话,也会抛出异常
        
        NSLog(@"执行accessInstanceVariablesDirectly方法");
        return YES;
    }
    
    @end
    

    ViewController.m文件

    #import "ViewController.h"
    #import "MJPeroson.h"
    
    @interface ViewController ()
    
    @property(nonatomic,strong)MJPeroson *person;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.person = [[MJPeroson alloc] init];
        
        NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld;
        [self.person addObserver:self forKeyPath:@"age" options:options context:nil];
    }
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //    这三种方法都可以成功设置self.person的age属性为10
    //    [self.person setValue:@10 forKey:@"age"];
    //    [self.person setValue:@(10) forKey:@"age"];
        [self.person setValue:[NSNumber numberWithInteger:10] forKey:@"age"];
    }
    
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
        NSLog(@"监听到%@的属性%@发生了变化----%@",object,keyPath,change);
    }
    
    -(void)dealloc{
        [self.person removeObserver:self forKeyPath:@"age"];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    @end
    
    

    原理图如下:


    屏幕快照 2018-10-04 下午2.41.28.png 屏幕快照 2018-10-04 下午2.39.56.png
    3、总结:

    <1>通过KVC修改属性会触发KVO么?
    肯定会。
    从上面也可以看出,当没有set方法的时候,使用KVC修改属性变量,KVO依然会触发,所以KVC内部应该也调用了willChangeValueForKey:key 和 didChangeValueForKey:key 方法,从而触发了KVO。

    <2>KVC的赋值和取值过程是怎样的?原理是什么?
    如上原理图所示

    相关文章

      网友评论

          本文标题:KVC知识点

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