美文网首页
iOS中KVC的底层实现流程

iOS中KVC的底层实现流程

作者: 一叶知秋0830 | 来源:发表于2020-01-05 13:42 被阅读0次

1. KVC的使用

KVC的全称是Key-Value Coding,也就是键值编码,我们可以通过一个key来设置或获取某个属性的值。KVC所用到的API如下:

// 通过key设置属性值
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;

// 通过key获取属性值
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key; 

我们看到设置和获取属性值的方法都有2个,一个是key一个是keyPath这两个有什么区别呢?直接看下面示例吧,我们先定义如下2个类:

// Dog类
#import <Foundation/Foundation.h>
@interface Dog : NSObject

@property (nonatomic , assign) NSInteger age;

@end

// Student类
#import <Foundation/Foundation.h>
#import "Dog.h"

@interface Student : NSObject

@property (nonatomic , strong) NSString *name;
@property (nonatomic , strong) Dog *dog;

@end

如果我们要设置或获取Student实例对象的name属性值,通过keykeyPath方式都是一样的:

- (void)test{
    self.stu1 = [[Student alloc] init];
    self.stu1.dog = [[Dog alloc] init];
    
    [self.stu1 setValue:@"Jack" forKey:@"name"];
    NSLog(@"通过key的方式--%@",[self.stu1 valueForKey:@"name"]);
    
    [self.stu1 setValue:@"Bob" forKeyPath:@"name"];
    NSLog(@"通过keyPath的方式--%@",[self.stu1 valueForKeyPath:@"name"]);
}

但是如果我们要设置或获取Student实例对象的dogage属性值,那就只能通过keyPath的方式了。此时如果还是使用key的方式设置属性值的话就会抛出setValue:forUndefinedKey:的异常。

- (void)test{
    self.stu1 = [[Student alloc] init];
    self.stu1.dog = [[Dog alloc] init];
  
    [self.stu1 setValue:@5 forKeyPath:@"dog.age"];
    NSLog(@"%@",[self.stu1 valueForKeyPath:@"dog.age"]);
}

2 KVC设置属性值的流程

我们以setValue:forKey:为例,KVC设置属性值的整个流程如下图所示:

KVC设置属性值的流程
比如我们执行[self.stu1 setValue:@"Jack" forKey:@"name"];这句代码,其底层执行流程如下:
  • 首先找到self.stu1isa指向的类对象,在类对象的方法列表中按照setName_setName的顺序进行查找(也就是先查找看有没有setName这个方法,没有的话再查找有没有_setName方法)。
  • 前面如果查找到了方法,就调用方法。
  • 前面如果没有查找到方法,底层就会调用Student类的+ (BOOL)accessInstanceVariablesDirectly;方法。如果返回值是YES就表示允许直接访问类的成员变量,返回NO表示不允许。这个方法是需要我们在Student类中重写的,由开发者来决定是否允许访问成员变量,如果不重写,默认是返回YES。
  • 如果上一步返回的是NO,那会直接抛出异常setValue:forUndefinedKey:
  • 如果返回的是YES的话,那就会按照_name_isNamenameisName这样一个顺序来查找类对象中的成员属性列表,如果找到了就直接赋值;如果没有找到就抛出异常setValue:forUndefinedKey:

3 KVC获取属性值的流程

KVC获取属性值的流程图如下:

KVC获取属性值的流程

比如我们执行[self.stu1 valueForKey:@"name"];这句代码,其底层执行流程如下:

  • 首先找到self.stu1的isa指向的类对象,在类对象的方法列表中按照getNamenameisName_name的顺序进行查找。
  • 上一步如果查找到了方法,就直接调用方法。
  • 如果没有找到方法,就会调用Student类的+ (BOOL)accessInstanceVariablesDirectly;方法,看其返回的是YES还是NO;
  • 如果上一步返回的是NO,就直接抛出异常valueForUndefinedKey:
  • 如果返回的是YES,就会按照_name_isNamenameisName这样一个顺序来查找类对象中的成员属性列表,如果找到了就直接取值;如果没有找到就抛出异常valueForUndefinedKey:

相关文章

  • iOS中KVC的底层实现流程

    1. KVC的使用 KVC的全称是Key-Value Coding,也就是键值编码,我们可以通过一个key来设置或...

  • iOS - KVO

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

  • KVC底层实现步骤

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

  • KVC

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

  • iOS KVC底层实现

    参考 https://ke.qq.com/course/314526 KVC KVC,俗称“键值编码”,可以通过一...

  • 可能碰到的iOS笔试面试题(7)--KVO-KVC

    KVC-KVO KVC的底层实现? KVO的底层实现? 什么是KVO和KVC? KVO的缺陷? KVO是一个对象能...

  • kvc kvo

    1.iOS底层-KVC使用实践以及实现原理赋值原理:(1)去模型中查找有没有setIcon方法,就直接调用这个se...

  • KVC /KVO的底层原理和使用场景

    1 KVC(KeyValueCoding) 1.1 KVC 常用的方法 1.2 KVC 底层实现原理 1.3 KV...

  • KVC /KVO的底层原理和使用场景

    1 KVC(KeyValueCoding) 1.1 KVC 常用的方法 1.2 KVC 底层实现原理 1.3 KV...

  • 九、KVC

    九、KVC 1.底层实现

网友评论

      本文标题:iOS中KVC的底层实现流程

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