KVC知识点

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 

@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 *)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 *)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知识点)