美文网首页
探寻KVC本质

探寻KVC本质

作者: 叫我小黑 | 来源:发表于2019-06-25 22:40 被阅读0次

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; 

setValue:forKey:的原理

//MJPerson
@interface MJPerson : NSObject
{
    @public
    int age;
    int isAge;
    int _isAge;
    int _age;
}
@end

@implementation MJPerson
- (void)setAge:(int)age
{
    NSLog(@"setAge: - %d", age);
}

- (void)_setAge:(int)age
{
    NSLog(@"_setAge: - %d", age);
}

// 默认的返回值就是YES
+ (BOOL)accessInstanceVariablesDirectly
{
    return YES;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MJPerson *person = [[MJPerson alloc] init];
        [person setValue:@10 forKey:@"age"];
    }
    return 0;
}

运行打印结果:

setValue:forKey: -1
setAge: 方法注释掉,重新运行打印结果:
setValue:forKey: -2
再将 _setAge: 方法注释掉,并将 accessInstanceVariablesDirectly 方法返回的结果设置为 NO,重新运行打印结果:
setValue:forKey: -3
accessInstanceVariablesDirectly 方法返回的结果设置为 YES,或直接注释掉,运行
setValue:forKey: -4
_age 注释掉,运行
setValue:forKey: -5
_isAge 注释掉,运行
setValue:forKey: -6
age 注释掉,运行
setValue:forKey: -6
isAge 注释掉,运行
setValue:forKey: -7

通过上面的操作,可得 setValue:forKey: 原理 如下


setValue:forKey: 原理

valueForKey:的原理

//MJPerson
@interface MJPerson : NSObject
{
    @public
    int age;
    int isAge;
    int _isAge;
    int _age;
}
@end

@implementation MJPerson
- (int)getAge
{
    return 14;
}

- (int)age
{
    return 15;
}

- (int)isAge
{
    return 16;
}

- (int)_age
{
    return 17;
}

 //默认的返回值就是YES
+ (BOOL)accessInstanceVariablesDirectly
{
    return YES;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MJPerson *person = [[MJPerson alloc] init];
        person->_age = 10;
        person->_isAge = 11;
        person->age = 12;
        person->isAge = 13;
        NSLog(@"%@", [person valueForKey:@"age"]);
    }
    return 0;
}

运行打印结果为

14

getAge 方法注释掉,运行打印结果为

15

再将 age 方法注释掉,运行打印结果为

16

再将 isAge 方法注释掉,运行打印结果为

17

再将 _age 方法注释掉,并将 accessInstanceVariablesDirectly 方法返回的结果设置为 NO,运行打印结果为

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MJPerson 0x1005074f0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key age.'

accessInstanceVariablesDirectly 方法返回的结果设置为 YES,或直接注释掉,运行打印结果为

10

_age 注释掉,运行打印结果为

11

_isAge 注释掉,运行打印结果为

12

age 注释掉,运行打印结果为

13

isAge 注释掉,运行打印结果为

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MJPerson 0x10056f0e0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key age.'

通过上面的操作,可得 valueForKey:的原理如下


valueForKey:的原理

思考:通过 KVC 修改属性会触发 KVO 么?

//MJPerson
@interface MJPerson : NSObject
@property (assign, nonatomic) int age;
@end
@implementation MJPerson
@end

//MJObserver
@interface MJObserver : NSObject
@end
@implementation MJObserver

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

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MJObserver *observer = [[MJObserver alloc] init];
        MJPerson *person = [[MJPerson alloc] init];
        
        // 添加KVO监听
        [person addObserver:observer forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
        // 通过KVC修改age属性
        [person setValue:@10 forKey:@"age"];
        // 移除KVO监听
        [person removeObserver:observer forKeyPath:@"age"];

    }
    return 0;
}

打印结果:


打印结果

由打印结果可看出,通过 KVC 修改属性会触发 KVO。

相关文章

  • 探寻KVC本质

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

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

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

  • 探寻KVO & KVC

    KVO KVO的本质是什么? KVO的全称是Key-Value Observing,可以用于监听某个对象属性值的改...

  • KVC本质

    在设置setValueForKey时,如果对象的属性添加了KVO观察,会调用KVO,即使设置的key没有通过set...

  • KVC本质

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

  • KVC本质

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

  • 处理Model (二) 使用KVC 方法及其本质

    .h文件 .m文件 KVC本质

  • swift kvc 构造函数

    kvc 是oc特有 ,KVC 本质上是在运行时,直接调用程序会崩溃 介绍 kvc 构造函数 kvc构造函数的作用是...

  • KVO和KVC的使用及原理解析

    一 KVO基本使用 二 KVO本质原理讲解及代码验证 三 KVC基本使用 四 KVC设值原理 五 KVC取值原理 ...

  • iOS底层原理总结 - 探寻block的本质(一)

    iOS底层原理总结 - 探寻block的本质(一) iOS底层原理总结 - 探寻block的本质(一)

网友评论

      本文标题:探寻KVC本质

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