iOS-KVO 实现原理
来源:互联网 发布:ubuntu下安装pyqt4 编辑:程序博客网 时间:2024/04/29 20:21
KVO 属性观察者 是观察者模式的一种具体实现,主要通过观察对象属性值的变化,触发对应的方法
下面学习下 KVO 的具体实现 和 底层实现原理
原生观察者实现
1、为 狗 对象 d
添加一个观察者为 自己, 同时监听对象 d
->age
年龄 属性的改变
Dog *d = [Dog new];[p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
2、实现观察者监听方法,实时监听 d
->age
年龄 属性的改变,并获取改变后的 new
值
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { NSLog(@"%@-%@", keyPath,change[@"new"]);}
3、在对象销毁前,移除狗对象的观察者
- (void)dealloc { [self.d removeObserver:self forKeyPath:@"age"];}
系统 KVO 的底层实现原理
- KVO 是基于 runtime 机制实现的
- 首先是给 NSObject 添加一个分类 (Category), 添加两个方法:
- 方法一:为自己添加观察者(observer)
- 方法二:属性变化后执行的动作(action)
- 为这个类的对象添加观察者
(方法一)
和实现属性变化后的动作方法(方法二)
- 当某个类的对象第一次被观察时
(方法一)
,系统就会在运行时动态地创建该类的一个派生类 - 在这个类中实现添加观察者方法
(方法一)
,并将观察者对象和自己关联起来,并将指针指向生成的派生类 - 在这个派生类中重写基类中被观察属性的
setter
方法,并获取对象的关联对象 - 然后在
setter
方法中,执行 关联对象 的方法二
,触发对象变化后的 action 动作,这样属性变化后的方法将会执行,达到监听的作用
具体代码实现
一、给 NSObject 添加一个分类 (Category), 添加两个方法,并空实现
@interface NSObject (KVO)- (void)xm_addObserver:( NSObject * _Nonnull )observer forKeyPath:(NSString * _Nonnull)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;- (void)xm_observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context;@end
@implementation NSObject (KVO)#pragma mark - 空实现- (void)xm_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context {}- (void)xm_observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {}@end
二、为某个类的对象添加观察者(方法一)
和实现属性变化后的动作方法(方法二)
Dog *d = [Dog new];[d xm_addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
- (void)xm_observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { NSLog(@"%@------%@", keyPath, change[@"new"]);}
三、当某个类的对象第一次被观察时(方法一)
,在运行时动态地创建该类的一个派生类
@interface KV0_Dog : Dog@end
四、在这个类中实现添加观察者方法(方法一)
,并将观察者对象和自己关联起来,并将指针指向生成的派生类
#import "Dog.h"#import <objc/message.h>@implementation Dog- (void)xm_addObserver:( NSObject * _Nonnull )observer forKeyPath:(NSString * _Nonnull)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context { // 修改对象的 ias 指针 object_setClass(self, NSClassFromString(@"KV0_Dog")); // 关联对象,将观察者对象和自己关联起来 objc_setAssociatedObject(self, "observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}@end
五、在这个派生类中重写基类中被观察属性的 setter
方法,并获取对象的关联对象,执行关联对象 的方法二
,触发对象变化后的 action
#import "KV0_Dog.h"#import <objc/message.h>#import "NSObject+KVO.h"@implementation KV0_Dog- (void)setAge:(NSInteger)age { // 重写父类的属性 setter 方法 [super setAge:age]; // 获取自己(父类)的关联对象,观察者对象 id observer = objc_getAssociatedObject(self, "observer"); // 触发观察者对象的 observeValueForKeyPath 方法, 并传递参数 [observer xm_observeValueForKeyPath:@"age" ofObject:self change:@{@"kind": @(1), @"new": @(age)} context:nil];}@end
六、改变 Dog
的 age
属性,然后 步骤二的属性观察方法将会被执行,同时属性改变的新值也传递过来了
打印结果
age------1age------2age------3age------4...
阅读全文
0 0
- iOS KVO 实现原理
- iOS-KVO 实现原理
- iOS kvo 底层实现原理
- iOS KVO底层实现原理
- iOS KVO的实现原理
- iOS的KVO底层实现原理
- iOS中KVO的底层实现原理
- iOS OC KVC KVO 实现原理详解
- iOS ---- KVO的内部实现原理
- iOS ---- KVO的内部实现原理
- iOS中KVO的实现原理
- ios KVO的使用和原理实现
- iOS KVC 和 KVO 原理实现
- ios-kvc\kvo 原理
- iOS KVO核心原理
- ios-KVO原理
- 解析KVO实现原理
- 解析KVO实现原理
- [C++] C/C++ 取整函数ceil(),floor()
- PHP之文件操作,http请求数据格式,模拟get和post,CURL模拟请求的使用
- Docker基础教程(7)-终焉-使用Docker部署一个web服务器
- ps快捷键
- java-队列,双端队列、栈
- iOS-KVO 实现原理
- C++11并发编程(一)——初始C++11多线程库
- 嵌入式Linux资料合集
- 【springmvc】@RequestParam详解以及加与不加的区别
- Java IO流的基本概念
- java-Map接口(查询表)
- json使用
- python ORM链接数据库-sqlalchemy库的使用(一)
- unity和lua的交互使用之tolua环境搭建过程