KVO实现原理探究

什么是KVO ?

KVO即Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。
简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。

KVO简单例子

新建一个Person类:

#import <Foundation/Foundation.h>

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

在控制器的ViewDidLoad方法里注册KVO监听,并改变键值。
#import "ViewController.h"
#import "Person.h"

@interface ViewController ()
@property (nonatomic, strong) Person *p;
@end

@implementation ViewController

- (void)viewDidLoad {
	[super viewDidLoad];

	Person *p = [[Person alloc] init];
	p.age = 20;
        
        //注册观察者
	[p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];

	p.age = 30;
	self.p = p;
}

/**
 *  当监控的某个属性的值改变了就会调用
 *
 *  @param keyPath 属性名(哪个属性改了?)
 *  @param object  哪个对象的属性被改了?
 *  @param change  属性的修改情况(属性原来的值、属性最新的值)
 *  @param context void * == id
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	NSLog(@"%@对象的%@属性改变了,由旧值%@改变为新值%@", object, keyPath, change[@"old"], change[@"new"]);
}

- (void)dealloc {
	//移除KVO监听
	[self.p removeObserver:self forKeyPath:@"age"];
}

@end

打印结果为:

2015-03-17 13:38:19.635 KVOTest[2001:60b] <Person: 0x15e5cf90>对象的age属性改变了,由旧值20改变为新值30

什么是isa ?

苹果官方是这样介绍isa的:
Every object is connected to the run-time system through its isa instance variable, inherited from the NSObject class. isa identifies the object's class; it points to a structure that's compiled from the class definition. Through isa, an object can find whatever information it needs at runtime such as its place in the inheritance hierarchy, the size and structure of its instance variables, and the location of the method implementations it can perform in response to messages.

通过一个实例对象的isa,我们可以找到这个对象的所有信息,如继承架构,实例变量的size和结构,响应消息机制对应的方法入口地址。

KVO前后的isa变化

变量p在KVO监听之前的isa,是Person类,如下:


在注册KVO监听之后的isa,是NSKVONotifying_Person类,如下:



结论

可见,在addObserver:forKeyPath:options:context:之后,对象p的isa变为了NSKVONotifying_Person。

所以,根据上面的isa介绍,响应setAge的方法,实际上是对象p的isa即NSKVONotifying_Person类的setAge方法,并不是原Person类的setAge方法。

可以大胆想象,NSKVONotifying_Person类是Person类的子类,在NSKVONotifying_Person类内部,重写了setAge方法,并且在setAge方法里让监听器调用了observeValueForKeyPath:ofObject:change:context:方法。

那么,NSKVONotifying_Person是怎么产生的呢?简单的说,是由runtime产生的。后续文章将介绍objective-c的runtime机制。


个人原创,欢迎转载,转载请注明出处:http://blog.csdn.net/iosHot

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值