KVO的实现原理分析
来源:互联网 发布:信鸽群发软件怎么样 编辑:程序博客网 时间:2024/06/05 19:58
先来介绍下KVO的基本概念:
KVO,即:Key-Value Observing,它提供一个机制,当指定的对象的属性发生了改变,则对象就会接收到通知。
也就是说它能时刻监听到属性的改变。
我们先来看个简单的例子:
首先,我创建了一个Student类,它有一个name属性:
#import <Foundation/Foundation.h>@interface Student : NSObject@property (nonatomic, copy) NSString *name;@end然后,我设计的是点击模拟器的屏幕,name后面的数字就会增加1,就会造成name的改变,紧接着在接受变更通知的
方法中打印出name的值,看是否能够监听到,代码如下:
#import "ViewController.h"#import "Student.h"@interface ViewController ()@property (nonatomic, strong) Student *student;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; Student *student = [[Student alloc] init]; self.student = student; //利用KVO监听Student类的name属性变化 [student addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];}//收到属性变更的通知,就会调用此方法- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { NSLog(@"%@", self.student.name);}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { static NSInteger i = 0; //每点击一次屏幕i就会+1 NSString *name = [NSString stringWithFormat:@"Ocean - %zd", i++]; self .student.name = name;}@end运行程序,连续点击模拟器的屏幕,打印结果如下:
可以看出能够监听到name值的每次改变。
这是怎么造成的呢?
通过我们知道的知识,每次进行属性的更改,都会调用它的set方法,KVO的监听会不会跟set方法有关?
带着这个疑问,我们接着探讨。
此时设计成对属性的改变,使它不调用set方法,看是否能够监听到属性的改变:
1.把Student类的name属性设置成公有的,可以供外部调用
#import <Foundation/Foundation.h>@interface Student : NSObject{ @public NSString *_name;}@property (nonatomic, copy) NSString *name;@end2.重写name的set方法,通过打印输出的方式知道set方法是否调用
#import "Student.h"@implementation Student- (void)setName:(NSString *)name { _name = name; NSLog(@"set方法被调用了");}@end3.更改修改name值的方式,用 -> 方式来修改,达到不调用set方法的目的,所以我只需修改上面的touchsBegan方法即可
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { static NSInteger i = 0; //每点击一次屏幕i就会+1 NSString *name = [NSString stringWithFormat:@"Ocean - %zd", i++];// self .student.name = name; //直接通过成员属性来修改name,不会调用其set方法 self.student -> _name = name;}做了上述修改后,运行程序,点击模拟器屏幕,控制台没有任何输出。
所以我们可以得出一个结论:KVO的本质就是监听对象有没有调用set方法。
那么又有一个问题,它是怎么监听有没有调用set方法呢?
仔细想下也不难想到,我们在开发中监听一个方法有没有调用,都是用到重写这个方法。
那么官方是怎么重写这个方法的呢?我们把代码恢复到以前的方式,通过断点的形势来观察它的isa指针:
运行程序,观察它的isa指针:
图示部分很容易观察到,系统内部自动创建了一个NSKVONotifying_student的类,来重写方法,达到监听的目的,
然后在重写的方法中把通知发出去。
总结如下:
1.自定义一个NSKVONotifying_Studet的子类
2.重写setName方法,在里面通知观察者
3.修改isa指针,指向NSKVONotifying_Studet类,好让外界调用这个子类。
为了能更好的看懂我写的博客,我尽量每次都贴出源码,源码都在我的GitHub中,需要源码的点击这里。
后面我会介绍运用runtime来自定义KVO,敬请期待...
- KVO的实现原理分析
- KVO/KVC 原理、实现分析
- KVO的实现原理
- KVO的实现原理
- KVO的实现原理
- KVO 的实现原理
- KVO的底层实现原理
- KVO内部的实现原理
- KVO的底层实现原理
- KVO的底层实现原理
- KVO的内部实现原理
- iOS KVO的实现原理
- KVO的底层实现原理
- KVO/KVC 实现原理进一步分析
- (三)如何自己动手实现 KVO,KVO的实现原理
- iOS的KVO底层实现原理
- KVO的原理和简单实现
- iOS中KVO的底层实现原理
- 创建文本节点createTextNode
- Android 中的 Service 全面总结
- Android UpdateApk 增量更新
- JNDI的简单配置与使用
- SOCKET,TCP/IP,UDP,HTTP,FTP总结
- KVO的实现原理分析
- 一小时搞定DIV+CSS
- Spring框架中获取bean的五种方法
- 译码
- [思考]两个云计算平台的葬礼
- CAS单点登陆更改认证方式和持久化ticket
- 顺序表应用1:多余元素的删除之移位算法
- Thinking in Java
- alter table *** add constraint