KVO的底层是怎么实现的?
1:KVO是基于Runtime机制实现的
2:当某个类的对象第一次被观察时,系统就会在运行期动态的创建该类的一个派生类,在这个派生类中重写基类以及被观察属性的setter方法,派生类在被重写的setter方法实现真正的通知机制(Person->NSKVONotifying_Person)
后面我们对KVO的底层进行一个分析
业务需求
人的年龄改变了,那么狗得知道人的年龄改变了
1:我们先新建一个项目
屏幕快照 2016-04-21 上午10.55.38.png2:新建两个类
a:一个Person类
Person 有一个age年龄属性
b: 一个Dog类
屏幕快照 2016-04-21 上午10.58.44.png3:我们在ViewController去实现点击屏幕修改person的年龄属性
#import "ViewController.h"
#import "Person.h"
#import "Dog.h"
@interface ViewController ()
@property (nonatomic, strong) Person *person;
@property (nonatomic, strong) Dog *dog;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.person = [[Person alloc]init];
self.dog = [[Dog alloc]init];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.person.age = 10;
}
@end
4:接下来再去给person增加一个方法
#import "ViewController.h"
#import "Person.h"
#import "Dog.h"
@interface ViewController ()
@property (nonatomic, strong) Person *person;
@property (nonatomic, strong) Dog *dog;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.person = [[Person alloc]init];
self.dog = [[Dog alloc]init];
//这个方法的意思是什么,就是让self.dog知道self.person,的age改变了,也就是self.dog成为self.person的监听
[self.person addObserver:self.dog forKeyPath:@"age" options:0 context:nil];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.person.age = 10;
}
@end
5:接下来我们去Dog类里面实现一个方法(注意注释)
#import "Dog.h"
@implementation Dog
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
//这个方法什么意思?来到这里其实就是狗知道了person的年龄改变了
NSLog(@"狗知道了%@的%@改变了",object,keyPath);
}
@end
6:我们把项目运行起来,看是否实现我们的需求
屏幕快照 2016-04-21 上午11.21.43.png可以看到,控制台输出了,狗知道了person的age改变了
7:此时我们就简单的实现了我们的需求,是用的是KVO去实现
那KVO的底层到底是怎么实现的呢?为什么会去调用Dog的
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
//这个方法什么意思?来到这里其实就是狗知道了person的年龄改变了
NSLog(@"狗知道了%@的%@改变了",object,keyPath);
}
8:其实是这样,我们KVO监听的属性被改变的时候,系统会给我们生存一个派生类,并且这个类是继承Person类的,并且在年龄改变的时候,会重写属性的setter方法
屏幕快照 2016-04-21 上午11.26.56.png可能大家还不觉得是真的重写了这个类的setter方法,我给大家看一下他Person的isa指针到底是啥。
Snip20160421_2.png
网友评论