美文网首页
03--KVC/KVO本质02--KVC 取值&赋值过程

03--KVC/KVO本质02--KVC 取值&赋值过程

作者: 修_远 | 来源:发表于2020-07-02 22:32 被阅读0次

[TOC]

本章主要探索 KVC 的取值和赋值过程

探索过程来源于官方文档:About Key-Value Coding

一、赋值过程的探索

准备条件

  • SRPerson
// 成员变量
{
    @public
    NSString* _name;
    NSString* _isName;
    NSString* name;
    NSString* isName;
}
  • 探索 key:name
[person setValue:@"setter" forKey:@"name"];

NSLog(@"%@-%@-%@-%@", person->_name, person->_isName, person->name, person->isName);
NSLog(@"%@-%@-%@", person->_isName, person->name, person->isName);
NSLog(@"%@-%@", person->name, person->isName);
NSLog(@"%@", person->isName);

1.1 _key

  • KVC 最先找到的是 _key,也就是 _name
_key

1.2 _isKey

{
    @public
//    NSString* _name;
    NSString* _isName;
    NSString* name;
    NSString* isName;
}
  • 如果没有找到 _key,则会找 _isKey
_isKey

1.3 key

{
    @public
//    NSString* _name;
//    NSString* _isName;
    NSString* name;
    NSString* isName;
}
  • 如果没有找到 _key_isKey,则会找 key
key

1.4 isKey

{
    @public
//    NSString* _name;
//    NSString* _isName;
//    NSString* name;
    NSString* isName;
}
  • 当上面都没找到时,会去找 isKey
isKey

setter 方法的流程(setter方法在成员变量之前)

  • setKey 流程方法
@implementation SRPerson
//MARK: - setKey. 的流程分析
- (void)setName:(NSString *)name{
    NSLog(@"%s - %@",__func__,name);
}

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

- (void)setIsName:(NSString *)name{
    NSLog(@"%s - %@",__func__,name);
}
@end
  • 成员变量
{
    @public
    NSString* _name;
    NSString* _isName;
    NSString* name;
    NSString* isName;
}
  • 测试代码
// 1. KVC - 设置值的过程
[person setValue:@"setter" forKey:@"name"];

NSLog(@"%@-%@-%@-%@", person->_name, person->_isName, person->name, person->isName);
NSLog(@"%@-%@-%@", person->_isName, person->name, person->isName);
NSLog(@"%@-%@", person->name, person->isName);
NSLog(@"%@", person->isName);

setKey

  • setter 方法在 成员变量的前面,最先查找的 setter 方法是:setKey
setKey

_setKey

  • 其次是:_setKey
_setKey

setIsKey

  • 最后是:setIsKey
setIsKey

二、取值过程的探索

准备条件

  • 成员变量
{
    @public
    NSString* _name;
    NSString* _isName;
    NSString* name;
    NSString* isName;
}
  • 测试代码
// 2. KVC - 取值过程
person->_name   = @"_name";
person->_isName = @"_isName";
person->name    = @"name";
person->isName  = @"isName";

NSLog(@"取值 : %@", [person valueForKey:@"name"]);

2.1 _key

  • 成员变量
{
    @public
    NSString* _name;
    NSString* _isName;
    NSString* name;
    NSString* isName;
}
_key

2.2 _isKey

  • 成员变量
{
    @public
    // NSString* _name;
    NSString* _isName;
    NSString* name;
    NSString* isName;
}
_isKey

2.3 key

  • 成员变量
{
    @public
    // NSString* _name;
   // NSString* _isName;
    NSString* name;
    NSString* isName;
}
key

isKey

  • 成员变量
{
    @public
    // NSString* _name;
   // NSString* _isName;
   // NSString* name;
    NSString* isName;
}
isKey

三、accessInstanceVariablesDirectly 方法

这个方法是提供:开启或关闭成员变量的赋值

  • YES:允许成员变量赋值
  • NO: 不允许成员变量赋值
+ (BOOL)accessInstanceVariablesDirectly{
    return NO;
}

当返回 NO 时,对成员变量赋值,会有什么结果?

从截图中可以看出来,程序闪退,提示 name 是未定义的 key

crash

四、KVC 流程总结

4.1 KVC原理:setValue 调用过程

  1. 先会查找 setter 方法

    • 查找顺序:setKey->_setKey->setIsKey
  2. 如果setter方法没找到,就找实例变量

    • accessInstanceVariablesDirectly 返回 YES
    • 查找顺序:_key->_isKey->key->isKey
    • 如果找到,直接给这些实例变量 设值
  3. 如果setter方法和实例变量都没找到,则执行 setValue:forUndefinedKey: 方法

4.2 KVC原理:valueForKey 调用过程

  1. 先会查找 getter 方法

    • 查找顺序:getKey->key->isKey->_key
    • 如果找到,则调到第5步
  2. 判断是否是 NSArray

    相当于获取一个 pens 的数组

    person.arr = @[@"pen0", @"pen1", @"pen2", @"pen3"];
    NSArray *array = [person valueForKey:@"pens"];
    

    通过方法映射将数组的值返回

    • countOf<Key>
    - (NSUInteger)countOfPens{
        NSLog(@"%s",__func__);
        return [self.arr count];
    }
    
    • objectIn<Key>AtIndex:
    - (id)objectInPensAtIndex:(NSUInteger)index {
        NSLog(@"%s",__func__);
        return [NSString stringWithFormat:@"pens %lu", index];
    }
    
  3. 判断是否是 NSSet
    集合的方法也类似,这里不需要了解的特别清楚,知道有这么一回事就行了

  4. 非集合类型

    • accessInstanceVariablesDirectly 返回 YES
    • 查找顺序:_key->_isKey->key->isKey
    • 如果找到,直接获取实例变量的值,然后继续执行步骤5
  5. 对象指针

    • 如果检索到的属性是对象指针,则只需返回结果
    • 如果值是NSNumber支持的标量类型,则将其存储在NSNumber实例中并返回。
    • 如果结果是不被NSNumber支持的标量类型,转换成NSValue对象并返回它。
  6. 如果以上都没有找到,则执行 valueForUndefinedKey: 方法

相关文章

  • 03--KVC/KVO本质02--KVC 取值&赋值过程

    [TOC] 本章主要探索 KVC 的取值和赋值过程探索过程来源于官方文档:About Key-Value Codi...

  • 底层4:KVC

    面试题:通过KVC修改的属性会触发KVO吗? 会触发KVO。 面试题:KVC的赋值和取值过程是怎样的?原理是什么?...

  • KVC本质

    1.赋值操作 2.取值操作 3.用赋值KVC操作是否会触发KVO

  • iOS面试题:KVC的赋值和取值过程是怎样的?KVO原理是什么?

    更多:iOS面试题大全 1、KVC赋值 2、 KVC取值 3、 KVO原理 KVO 是 Objective-C 对...

  • 03--KVC/KVO本质05--KVO 本质

    [TOC] (一)KVO 初探 1. 基本用法 添加观察 监听观察 移除观察 通知使用完之后,一定要移除,否则会有...

  • KVC

    01基本使用 通过KVC修改属性会触发KVO么?会触发KVOKVC的赋值和取值过程是怎样的?原理是什么? KVC的...

  • KVC 的本质

    问?直接修改成员变量会触发KVO么?KVC的赋值和取值过程是怎样的?原理是什么? KVC的全称是Key-Value...

  • KVC 赋值过程、取值过程

    赋值过程 1.先找相关方法 set:, _set:, setIs:2.若没有相关方法...

  • KVC

    通过KVC修改属性会触发KVO吗 KVC的赋值和取值过程是怎么样的 原理是什么 KVC 常见的API有 setVa...

  • iOS底层原理 - 探寻KVC本质

    面试题引发的思考: Q: KVC的赋值和取值过程是怎样的?原理是什么?Q: 通过KVC修改属性会触发KVO么? 1...

网友评论

      本文标题:03--KVC/KVO本质02--KVC 取值&赋值过程

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