且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

KVO 其原理探究

更新时间:2022-08-22 16:57:31

什么是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 其原理探究

在注冊KVO监听之后的isa,是NSKVONotifying_Person类。例如以下:

KVO 其原理探究


结论

可见。在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

版权声明:本文博客原创文章。博客,未经同意,不得转载。







本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4722184.html,如需转载请自行联系原作者