KVO/KVC 实现机理分析
来源:http://blog.csdn.net/dqjyong/article/details/7672865
Objective-C里面的Key-Value Observing (KVO)机制,非常不错,可以很好的减少浇水代码。关于KVO的学习,可以参考文章:《Key-Value Observing快速入门》:http://www.cocoadev.cn/Objective-C/Key-Value-Observing-Quick-Start-cn.asp
KVO概念:
KVO是cocoa中的一个核心概念,简单理解就是:关注Model某个数据(Key)的对象可以注册为监听器,一旦Model某个Key的Value发生变化,就会广播给所有的监听器
KVO机制:
KVO(Key Value Observe)是cocoa中用来设值或取值的协议(NSKeyValueCoding),跟java的ejb有点类似,通过对变量和函数名进行规范达 到方便设置类成员值的目的。它有点类似于Notification,但是,它提供了观察某一属性变化的方法,而Notification需要一个发送 notification的对象,这样KVO就比Notification极大的简化了代码。
这种观察-被观察模型适用于这样的情况,比方说根据A(数据类)的某个属性值变化,B(view类)中的某个属性做出相应变化。对于推崇MVC的cocoa而言,kvo应用价值很高。
Key-Value Coding(KVC)实现分析
KVC运用了一个isa-swizzling技术。isa-swizzling就是类型混合指针机制。KVC主要通过isa-
swizzling,来实现其内部查找定位的。isa指针,如其名称所指,(就是is a kind
of的意思),指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针,和其它数据。
比如说如下的一行KVC的代码:
[site setValue:@"sitename" forKey:@"name"];
就会被编译器处理成:
SEL sel = sel_get_uid ("setValue:forKey:");
IMP method = objc_msg_lookup (site->isa,sel);
method(site, sel, @"sitename", @"name");
首先介绍两个基本概念:
(1)SEL数据类型:它是编译器运行Objective-C里的方法的环境参数。
(2)IMP数据类型:他其实就是一个编译器内部实现时候的函数指针。当Objective-C编译器去处理实现一个方法的时候,就会指向一个IMP对象,这个对象是C语言表述的类型。
关于如何找到实现函数的指针,可参考文章:《Objective-C如何避免动态绑定,而获得方法地址》:http://www.cocoadev.cn/Objective-C/Get-method-address.asp
这下KVC内部的实现就很清楚的清楚了:一个对象在调用setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。
Key-Value Observing(KVO)实现
在上面所介绍的KVC机制上加上KVO的自动观察消息通知机制就水到渠成了。
当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以isa指
针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。
熟悉KVO的朋友都知道,只有当我们调用KVC去访问key值的时候KVO才会起作用。所以肯定确定的是,KVO是基于KVC实现的。其实看了上面我们的分析以后,关系KVO的架构的构思也就水到渠成了。
因为KVC的实现机制,可以很容易看到某个KVC操作的Key,而后也很容易的跟观察者注册表中的Key进行匹对。假如访问的Key是被观察的Key,那么我们在内部就可以很容易的到观察者注册表中去找到观察者对象,而后给他发送消息。
=======================================================
对kvo/kvc做了简单的介绍,可作为入门读物。
有些术语描述不够精确请指正。
欢迎讨论。
KVO是Cocoa的一个重要机制,他提供了观察某一属性变化的方法,极大的简化了代码。这种观察-被观察模型适用于这样的情况,比方说根据A(数
据类)的某个属性值变化,B(view类)中的某个属性做出相应变化。对于推崇MVC的cocoa而言,kvo应用的地方非常广泛。
适用kvo时,通常遵循如下流程:
1 注册:
-(void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context
keyPath就是要观察的属性值,options给你观察键值变化的选择,而context方便传输你需要的数据(注意这是一个void型)
2 实现变化方法:
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void*)context
change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。
是不是很简单?kvo的逻辑非常清晰,实现步骤简单。
说了这么多,大家都要跃跃欲试了吧。可是,在此之前,我们还需要了解KVC机制。其实,知道了kvo的逻辑只是帮助你理解而已,要真正掌握的,不在 于kvo的实现步骤是什么,而在于KVC,因为只有符合KVC标准的对象才能使用kvo(强烈推荐要使用kvo的人先理解KVC)。
KVC是一种间接访问对象属性(用字符串表征)的机制,而不是直接调用对象的accessor方法或是直接访问成员对象。
key就是确定对象某个值的字符串,它通常和accessor方法或是变量同名,并且必须以小写字母开头。Keypath就是以“.”分隔的key,因为属性值也能包含属性。比如我们可以person这样的key,也可以有key.gender这样的key path。
获取属性值时可以通过valueForKey:的方法,设置属性值用setValue:forKey:。与此同时,KVC还对未定义的属性值定义了 valueForUndefinedKey:,你可以重载以获取你要的实现(补充下,KVC定义载NSKeyValueCoding的非正式协议里)。
在O-C 2.0引入了property,我们也可以通过.运算符来访问属性。下面直接看个例子:
@property NSInteger number;
instance.number = 3;
[instance setValue:[NSNumber numberWithInteger:3] forKey:@"number"];
注意KVC中的value都必须是对象。
以上介绍了通过KVC来获取/设置属性,接下来要说明下实现KVC的访问器方法(accessor method)。Apple给出的惯例通常是:
-key:,以及setKey:(使用的name convention和setter/getter命名一致)。对于未定义的属性可以用setNilValueForKey:。
至此,KVC的基本概念你应该已经掌握了。之所以是基本,因为只涉及到了单值情况,kvc还可以运用到对多关系,这里就不说了,留给各位自我学习的空间
接下来,我们要以集合为例,来对掌握的KVC进行一下实践。
之所以选择array,因为在ios中,array往往做为tableview的数据源,有这样的一种情况:
假设我们已经有N条数据,在进行了某个操作后,有在原先的数据后多了2条记录;或者对N中的某些数据进行更新替换。不使用KVC我们可以使用
reloadData方法或reloadRowsAtIndexPaths。前一种的弊端在于如果N很大消耗就很大。试想你只添加了几条数据却要重载之前
N数据。后一种方法的不足在于代码会很冗余,你要一次计算各个indexPath再去reload,而且还要提前想好究竟在哪些情况下会引起数据更新,
倘若使用了KVC/kvo,这样的麻烦就迎刃而解了,你将不用关心追加或是更新多少条数据。
下面将以添加数据为例,说明需要实现的方法:
实现insertObject:inKeyAtIndex:或者insertKey:atIndexes。同时在kvo中我们可以通过change这个dictionary得知发生了哪种变化,从而进行相应的处理。
http://www.cocoadev.cn/Objective-C/Key-Value-Observing-Quick-Start-cn.asp
KVO与Notification之间的区别:
notification是需要一个发送notification的对象,一般是notificationCenter,来通知观察者。
KVO是直接通知到观察对象,并且逻辑非常清晰,实现步骤简单。
KVO/KVC 实现机理分析的更多相关文章
- KVO/KVC总结
KVO/KVC总结 下面是根据网上文章的总结,方便查看. 在网上看别人的文章,了解KVC.KVO,有个kvo-kvc的例子,就是改变数组的内容(插入和删除),同步改变tableview中的 ...
- iOS:KVO/KVC 的概述与使用
iOS:KVO/KVC 的概述与使用 KVO APP开发技术QQ群:347072638 一,概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性 ...
- iOS KVO & KVC
键值观察:值更改时通知观察者 键值观察(Key-value observing,或简称 KVO)允许对象观察另一个对象的属性.该属性值改变时,会通知观察对象.它了解新值以及旧值:如果观察的属性为对多的 ...
- 【转】 iOS KVO KVC
原文: http://www.cocoachina.com/industry/20140224/7866.html Key Value Coding Key Value Coding是cocoa的一个 ...
- 设计模式之观察者模式(关于OC中的KVO\KVC\NSNotification)
学习了这么久的设计模式方面的知识,最大的感触就是,设计模式不能脱离语言特性.近段时间所看的两本书籍,<大话设计模式>里面的代码是C#写的,有一些设计模式实现起来也是采用了C#的语言特性(C ...
- iOS编程——Objective-C KVO/KVC机制[转]
这两天在看和这个相关的的内容,全部推翻重写一个版本,这是公司内做技术分享的文档总结,对结构.条理做了更清晰的调整.先找了段代码,理解下,网上看到最多的一段的关于KVC的代码 先上代码 1. 1 ...
- kvo&kvc
Key Value Coding Key Value Coding是cocoa的一个标准组成部分,它能让我们可以通过name(key)的方式访问property, 不必调用明确的property ac ...
- iOS编程——Objective-C KVO/KVC机制
来源:http://blog.sina.com.cn/s/blog_b0c59541010151s0.html 这两天在看和这个相关的的内容,全部推翻重写一个版本,这是公司内做技术分享的文档总结,对结 ...
- IOS基础之(十四) KVO/KVC
资料参考: http://www.cnblogs.com/kenshincui/p/3871178.html http://www.cnblogs.com/stoic/archive/2012/07/ ...
随机推荐
- javascript画直线和画圆的方法(非HTML5的方法)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Foundation框架—集合
Foundation框架—集合 一.NSArray和NSMutableArray (一)NSArray不可变数组 (1)NSArray的基本介绍 NSArray是OC中使用的数组,是面向对象的,以面向 ...
- FileUpload V2.1详细
Uploadify是JQuery的一个上传插件,实现的效果非常不错,带进度显示.不过官方提供的实例时php版本的,本文将详细介绍Uploadify在Aspnet中的使用,您也可以点击下面的链接进行演示 ...
- Gridview布局界面练习Base Adapter
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZcAAAJVCAIAAACdzC94AAAgAElEQVR4nOy953Ij2bGuLTVJmFrelf
- 一些iOS心得
ARC 1,arc是什么? automatic referece counting mrc mannualiOS5 之后出来的技术// 2,arc的原理是什么?// 在程序编译的时候,系统帮我 ...
- wpf中UserControl的几种绑定方式
我们经常会抽取一些可重用的控件,某个属性是否需要重用,直接决定了这个属性的绑定方式. 1.完全不可重用的控件 有一些与业务强相关的控件,它们的属性完全来自ViewModel,越是相对复杂的控件,越容易 ...
- LeetCode 笔记系列 20 Interleaving String [动态规划的抽象]
题目: Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given: ...
- Xml Schema:C#访问在complextype中插入新元素
最近用c#写Xml Schema代码,找了很久也找不到如何在已有的complextype中插入新的element,最后我充分发挥自己的聪明才智,哈哈,终于从...中找到了灵感. XmlSchemaSe ...
- CentOS 6.5设置静态IP教程 并且可以ping通
CentOS6.5掉电或重启,它的IP会被DHCP重新分配,如果要远程控制这台电脑,不得不去打开显示器去查看它的新IP,这样太麻烦了.于是需要将这台电脑的IP设置成静态的. 网上常规的设置静态ip的方 ...
- cache是什么文件?
通常人们所说的Cache就是指缓存SRAM. SRAM叫静态内存,"静态"指的是当我们将一笔数据写入SRAM后,除非重新写入新数据或关闭电源,否则写入的数据保持不变. 由于CPU的 ...