KVC 、KVO的本质

KVC/KVO实现的根本是Objective-C的动态性和runtime动态运行时isa-swizzling方法

1、KVC简介
全称是Key-value coding,翻译成键值编码。顾名思义,在某种程度上跟map的关系匪浅。它提供了一种使用字符串而不是访问器方法去访问一个对象实例变量的机制。
2、KVO简介
全称是Key-value observing,翻译成键值观察。提供了一种当其它对象属性被修改的时候能通知当前对象的机制。再MVC大行其道的Cocoa中,KVO机制很适合实现model和controller类之间的通讯。

实现原理
1、KVC如何访问属性值?

在某种程度上KVC提供了访问器的替代方案。
不过访问器方法是一个很好的东西,以至于只要是有可能,KVC也尽量再访问器方法的帮助下工作。

为了设置或者返回对象属性,KVC按顺序使用如下技术:
首先查找Set<Key>方法,然后按照_key,_iskey,key,iskey的顺序搜索方法。
如果仍为找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。这两个方法的默认实现都是抛出异常,我们可以根据需要重写它们。

2、KVC相关技术

2.1、 Key和Key Path

KVC定义了一种按名称访问对象属性的机制,支持这种访问的4个主要方法是:

-(id)valueForKey:(NSString *)key;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

前边两个方法用到的Key较容易理解,就是要访问的属性名称对应的字符串。
后面两个方法用到的KeyPath是一个被点操作符隔开的用于访问对象的指定属性的字符串序列。比如KeyPath address.street将会访问消息接收对象所包含的address属性中包含的一个street属性。其实KeyPath说白了就是我们平时使用点操作访问某个对象的属性时所写的那个字符串。
2.2、点语法和KVC

在实现了访问器方法的类中,使用点语法和KVC访问对象其实差别不大,二者可以任意混用。但是没有访问起方法的类中,点语法无法使用,这时KVC就有优势了。( 原因见第三部分的第一节:KVC如何访问属性值。

2.3、键值验证(Key-Value Validation)

KVC提供了验证Key对应的Value是否可用的方法:
- (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
该方法默认的实现是调用一个如下格式的方法:
- (BOOL)validate<Key>:error:

注意:KVC是不会自动调用键值验证方法的 ,就是说我们需要手动验证。但是有些技术,比如CoreData会自动调用。

KVO本质

当某个类的实例对象的key第一次被观察时,系统就会在运行期动态地创建该类的一个派生类NSKVONotifying_类名,在这个派生类中重写该类中被观察的属性的 setter 方法。

KVO的原理是什么?

苹果官方文档

Key-Value Observing Implementation Details

Automatic key-value observing is implemented using a technique called isa-swizzling.
The isa pointer, as the name suggests, points to the object's class which maintains a dispatch table. This dispatch table essentially contains pointers to the methods the class implements, among other data.
When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. As a result the value of the isa pointer does not necessarily reflect the actual class of the instance.
You should never rely on the isa pointer to determine class membership. Instead, you should use the class method to determine the class of an object instance.

实现原理:

当某个类的对象被观察时,系统的runtime运行时会动态的实现一个基于该类的一个中间类(派生类),在中间类中实现被观察基类属性的setter方法,中间类在重写的setter方法中实现真正的通知机制。

**同时派生类还重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的 isa 指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对 setter 的调用就会调用重写的 setter,从而激活键值通知机制。此外,派生类还重写了 dealloc 方法来释放资源。
**

新的中间类NSKVONotifying_Person会重写监听的属性对应的以下方法:

set方法class方法dealloc方法_isKVO

①class
重写class方法是为了我们调用它的时候返回跟重写继承类之前同样的内容。

②重写set方法
新类会重写对应的set方法,是为了在set方法中增加另外两个方法的调用:
- (void)willChangeValueForKey:(NSString *)key
- (void)didChangeValueForKey:(NSString *)key
其中,didChangeValueForKey:方法负责调用:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
这就是KVO实现的原理!
如果没有任何的访问器方法,-setValue:forKey方法会直接调用:
- (void)willChangeValueForKey:(NSString *)key
- (void)didChangeValueForKey:(NSString *)key
如果在没有使用键值编码且没有使用适当命名的访问起方法的时候,我们可以直接调用上述两个方法,同样可以使用KVO!

参考:
原文作者wangzz
[深入浅出Cocoa]详解键值观察(KVO)及其实现机理](http://blog.csdn.net/kesalin/article/details/8194240)
如果你对类和对象的关系不太明白阅读:深入浅出Cocoa之类与对象

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

推荐阅读更多精彩内容