KVC和KVO原理解析

KVC 键值编码(Key-value coding)

KVC是一套方便我们用字符串来操作对象的机制,可以使得操作对象时跟操作字典一样的灵活。在字典转模型的领域中应用起来极为方便,并且KVC可以轻松的帮我们突破访问限制的一些问题,直接访问到私有成员

  • 主要方法
- (id)valueForKey:(NSString *)key;  
- (void)setValue:(id)value forKey:(NSString *)key; 
//如果需要操作访问一些“属性里的属性”时,就用带Path的方法来操作 
- (id)valueForKeyPath:(NSString *)keyPath;  
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
  • KVC的优点
    (1). 无论类中的成员是否私有,用KVC都可以对它们正常取值和赋值
    比如当属性在扩展里面 无法通过点语法赋值 可以通过kvc赋值
    (2). 不管你的成员变量是否加下划线,你用KVC取值和赋值时传入的属性名都可以不带下划线
    (3). 大大简化字典转模型代码,KVC提供了一套更简洁的操作方式,只需你传入一个字典,就可以帮你自动把字典里的每一项赋值给你实体类对应的属性
NSDictionary *dic = @{
                          @"name":@"test",
//KVC中,赋值时传入的值都只能是对象类型,无法直接传入基本数据类型
                          @"age":@18,
                          @"address":@"China"
                          };
    [p setValuesForKeysWithDictionary:dic];
    NSLog(@"name:%@ age:%ld address:%@",p.name,p.age,p.address);
  • KVC缺点:
    1.在编码时很容易输错key导致问题
    解决办法:用KVC时传入的Key必须保证类中存在同名的属性。否则会运行时崩溃。如果不希望运行时直接崩溃,就需要在类里重写setValue:值 forUndefinedKey:键方法,这样,当用KVC对Person对象赋值了一个Key与属性对应不上的错误时,系统会自动调用这个方法.
    2.语法相较点语法而言也略微繁琐。
    解决办法:用runtime取代

  • 实现方法:
    KVC运用了一个isa-swizzling技术,任何对象都有isa指针。KVC主要通过isa-swizzling,来实现其内部查找定位的:
    (1) 实例方法调用时,通过对象的 isa 在类中获取方法的实现
    (2) 类方法调用时,通过类的 isa 在元类中获取方法的实现

  • KVC的赋值原理:

@implementation Person {
    NSString *_address;
}

Person *p  =[[Person alloc] init];
[p setValue:@"China" forKey:@"address"];
NSString *ads = [p valueForKey:@"address"];

找的顺序是 setAddress:==>_address==>_isAddress==>address==>isAddress

  1. 用KVC赋值时,会优先调用set<Key>:属性值方法(setAddress:(NSString *)address)
  2. 如果找不到,则会先找带下划线的成员变量_<key>(_address),再找_is<Key>(_isAddress),如果找到则赋值
  3. 如果上面都找不到,则会先查找不带下划线的成员变量<key>(address),再找is<Key>(isAddress),找到则赋值
  4. 如果上面列出的方法或者成员变量都不存在,系统将会执行该对象的setValue:forUNdefinedKey:方法,默认是抛出异常
    5.如果想让这个类禁用KVC,那么重写+ (BOOL)accessInstanceVariablesDirectly方法让其返回NO即可,这样的话如果KVC没有找到set<Key>:属性名时,会直接用setValue:forUndefinedKey:方法.

KVO 键值观察Key-value observing)

  • 实现原理
    当你观察一个对象时,一个新的类会动态被创建。这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法。自然,重写的 setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象值的更改。最后把这个对象的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例。
    原来,这个中间类,继承自原本的那个类。不仅如此,Apple 还重写了 -class 方法,企图欺骗我们这个类没有变,就是原本那个类。

简单的说就是在给某个类的属性添加观察的时候,系统就创建一个该类派生类,然后派生类重写该属性的setter方法实现观察对象的改变,然后将这个对象的 isa 指针指向这个派生类。对象就变成了新创建的子类的实例。
它是基于KVC实现的,实现了响应式编程,内部实现运用了runtime的特性。
下面这篇文章介绍了如何手动实现KVO
http://tech.glowing.com/cn/implement-kvo/

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

推荐阅读更多精彩内容