iOS-底层原理(5)-KVC底层原理详解

面试题
1. 通过KVC修改属性会触发KVO么?
  • 会触发KVO

代码例子佐证

@interface Person : NSObject
@property (assign, nonatomic) int age;
@end

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

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Observer.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Observer *observer = [[Observer alloc] init];
        Person *person = [[Person 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.png
2. KVC的赋值和取值过程是怎样的?原理是什么?
  • 详情见下文的valueForKey:的原理图
序言

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:的原理
image.png

代码例子佐证

  • accessInstanceVariablesDirectly返回NO
// 默认的返回值就是YES
+ (BOOL)accessInstanceVariablesDirectly {
    return NO;
}
image.png
  • accessInstanceVariablesDirectly返回YES,并且有下划线成员变量
@interface Person : NSObject {
@public
    int age;
    int isAge;
    int _isAge;
    int _age;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Person *person = [[Person alloc] init];
        // 通过KVC修改age属性
        [person setValue:@10 forKey:@"age"];
        
        NSLog(@"%@", [person valueForKey:@"age"]);
    }
    return 0;
}

运行结果

image.png

可以将变量依次注释,看看打印结果ageisAge_isAge_age

@public
    int age;
    int isAge;
//    int _isAge;
//    int _age;
}

运行结果

image.png
valueForKey:的原理
valueForKey.png
  • 代码例子佐证 - 先找方法
@implementation Person

// 第一顺序调用
- (int)getAge {
    return 11;
}

// 第二顺序调用
- (int)age {
    return 12;
}

// 第三顺序调用
- (int)isAge {
    return 13;
}

// 第四顺序调用
- (int)_age {
    return 14;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Person *person = [[Person alloc] init];

        NSLog(@"%@", [person valueForKey:@"age"]);
    }
    return 0;
}
  • 依次注释掉方法getAgeageisAge_age,然后打印结果如下
getAge.png
age.png
isAge.png
_age.png
  • 代码例子佐证 - 再找成员变量
@interface Person : NSObject {
@public
    int age;
    int isAge;
    int _isAge;
    int _age;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Person *person = [[Person alloc] init];
        // 通过KVC修改age属性
        person->_age = 100;
        person->_isAge = 110;
        person->age = 120;
        person->isAge = 130;
        
        NSLog(@"%@", [person valueForKey:@"age"]);
    }
    return 0;
}
  • 依次在Person.h文件中注释成员变量_age_isAgeageisAge,然后查看打印结果
_age.png
_isAge.png
age.png
isAge.png

如果将方法和成员变量全部去掉,打印结果如下

image.png

由打印结果可知,如果方法和成员变量都找不到,则最终方法找不到的错误。


本文参考借鉴MJ的教程视频,非常感谢.


项目连接地址 - iOS-KVC

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • KVC KVC定义 KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过K...
    暮年古稀ZC阅读 2,127评论 2 9
  • KVC(Key-value coding)键值编码,单看这个名字可能不太好理解。其实翻译一下就很简单了,就是指iO...
    朽木自雕也阅读 1,546评论 6 1
  • KVC(Key-valuecoding)键值编码,单看这个名字可能不太好理解。其实翻译一下就很简单了,就是指iOS...
    榕樹頭阅读 691评论 0 2
  • KVC KVC定义 KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过K...
    jackyshan阅读 51,792评论 9 200
  • KVC(Key-value coding)键值编码,单看这个名字可能不太好理解。其实翻译一下就很简单了,就是指iO...
    我的梦工厂阅读 889评论 1 8