美文网首页
iOS底层系列26 -- KVC

iOS底层系列26 -- KVC

作者: YanZi_33 | 来源:发表于2021-01-27 16:10 被阅读0次

KVC定义

  • KVC的全称是Key-Value Coding,中文就是我们所熟知的键值编码,键值编码是NSKeyValueCoding非正式协议启用的一种机制,通过key值字符串访问对象属性,这种间接的访问机制补充了实例变量及其相关的访问器方法所提供的直接访问;

KVC的常见API

在Xcode中直接搜索NSKeyValueCoding,看到NSKeyValueCoding是在Foundation框架中以给目标类添加category的形式实现的,主要目标类为NSObject对象类和存储数据的容器类;

Snip20210127_74.png
  • 最常见的API:
- (nullable id)valueForKey:(NSString *)key;
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;

KVC底层实现原理

1. NSObject类 --> setter方法赋值的底层实现
  • 在调用setValue: forKey:方法时,其底层实现一般分为下面几个步骤:
    • 第一步:目标对象类会按照setKey,_setKey,setIsKey的顺序去查找set方法,按照顺序只要找到其中一个set方法,就直接去执行赋值操作且不会再往下执行其他的set方法;
    • 第二步:如果第一步没有找到set方法,那么会去调用accessInstanceVariablesDirectly函数;
      • accessInstanceVariablesDirectly若返回YES(默认返回YES),表明可以去访问实例变量,会按照_key,_iskey,key,iskey的顺序搜索实例变量(Key指成员变量),只要找到其中一个,就直接赋值,若都没有找到,则进入第三步;
      • 若返回NO,表明既没有找到set方法也不能去访问实例变量,则进入第三步;
    • 第三步:来到这一步说明set方法和实例变量都没有找到,系统会检测该类是否有实现setValue: forUndefinedKey: 方法,如果该方法没有手动实现,则会抛出NSUndefinedKeyException类型异常;
  • 流程图如下所示:
Snip20210127_76.png
  • 代码实现:
@interface YYPerson : NSObject
{
    @public
    //sex 0-男 / 1-女
    //定义四个实例变量
    //按照顺序:_key,_isKey,key,isKey查找实例变量
    NSString *_sex;
    NSString *_isSex;
    NSString *sex;
    NSString *isSex;
}
@end
@implementation YYPerson

//按照顺序:setKey,_setKey,setIsKey查找set方法
- (void)setSex:(NSString *)value{
    NSLog(@"%s - %@", __func__, value);
}

- (void)_setSex:(NSString *)value{
    NSLog(@"%s - %@", __func__, value);
}

- (void)setIsSex:(NSString *)value{
    NSLog(@"%s - %@", __func__, value);
}

+ (BOOL)accessInstanceVariablesDirectly{
    return YES;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"设置出现异常!!!");
}

@end
NSObject类 --> getter方法取值的底层实现
  • 在调用valueForKey:方法时,其底层实现一般分为下面几个步骤:
    • 第一步:目标对象类会按照getKey,key,isKey,_key的顺序去查找get方法,只要找到其中一个get方法,就会立即执行获取到值,且不会再调用后面的get方法;
    • 第二步:如果第一步没有找到对应的get方法,那么调用 accessInstanceVariablesDirectly函数
      • 若返回值为YES,表明可以访问实例变量,会像上面的设值过程一样去查询实例变量_key,_isKey,key, 如果查询到符合条件的实例变量,会直接取出实例变量的值,反之执行第3步;
      • 若返回值为NO,表明不可以访问实例变量,直接执行第3步;
    • 第三步:系统会检测该类是否有实现valueForUndefinedKey:方法,如果该方法没有实现,则会抛出NSUndefinedKeyException类型异常;
  • 流程图如下所示:
Snip20210127_77.png
@implementation YYPerson

//按照顺序getKey,key,isKey,_key查找get方法
- (NSString *)getSex{
    return self->sex;
}

- (NSString *)sex{
    return self->sex;
}

- (NSString *)isSex{
    return self->isSex;
}

- (NSString *)_sex{
    return self->_sex;
}

+ (BOOL)accessInstanceVariablesDirectly{
    return NO;
}

- (id)valueForUndefinedKey:(NSString *)key{
    NSLog(@"取值出现异常!!!");
    return nil;
}

面试题一:KVC设置属性能否触发KVO监听回调

  • 测试代码:
- (void)viewDidLoad {
    [super viewDidLoad];

    self.person1 = [[YYPerson alloc]init];
    self.person1.name = @"a";

    [self.person1 addObserver:self forKeyPath:@"name" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@" change = %@",change);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.person1 setValue:@"aaa" forKey:@"name"];
}
  • 控制台调试结果:
Snip20210625_18.png
  • KVC底层是通过set方法实现的,所以能触发KVO的监听回调函数;

相关文章

  • iOS底层系列26 -- KVC

    KVC定义 KVC的全称是Key-Value Coding,中文就是我们所熟知的键值编码,键值编码是NSKeyVa...

  • KVC

    KVC原理剖析 - CocoaChina_让移动开发更简单 iOS开发底层细究:KVC和KVO底层原理 | iOS...

  • KVC

    iOS 如何使用KVC iOS开发UI篇—Kvc简单介绍 iOS开发系列--Objective-C之KVC、KVO

  • iOS开发技巧系列---详解KVC(我告诉你KVC的一切)

    iOS开发技巧系列---详解KVC(我告诉你KVC的一切) iOS开发技巧系列---详解KVC(我告诉你KVC的一切)

  • iOS底层系列:KVC

    前言 今天我们简单聊一下KVC,键值编码。平时我们给属性赋值或者取值都是使用点语法,调用属性的set或者get方法...

  • KVC 和 KVO

    iOS-KVC和KVO精炼讲解(干货)KVC 和 KVOiOS开发系列--Objective-C之KVC、KVO细...

  • OC--KVC

    参考:iOS开发技巧系列---详解KVC(我告诉你KVC的一切)KVC原理剖析 NSObject(NSKeyVal...

  • KVC底层实现步骤

    参考 iOS底层-KVC使用实践以及实现原理 [a setValue:value forKeyPath:@"ico...

  • iOS - KVO

    [toc] 参考 KVO KVC 【 iOS--KVO的实现原理与具体应用 】 【 IOS-详解KVO底层实现 】...

  • iOS 底层探索 - 类

    iOS 底层探索系列iOS 底层探索 - alloc & initiOS 底层探索 - calloc 和 is...

网友评论

      本文标题:iOS底层系列26 -- KVC

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