KVO分析

简介: KVO 概述 KVO的全称是NSKeyValueObserving,对象采用的一种非正式协议,当其他对象的指定属性发生变化时,通知对象。由于KVO的机制,只对对象的属性起作用,一般继承自NSObject都支持KVO。

KVO

概述

KVO的全称是NSKeyValueObserving,对象采用的一种非正式协议,当其他对象的指定属性发生变化时,通知对象。由于KVO的机制,只对对象的属性起作用,一般继承自NSObject都支持KVO。

您可以观察任何对象属性,包括简单属性、一对一关系和多对多关系。

使用

KVO使用通常需要三个步骤

  1. 通过 addObserver:forKeyPath:options:context:注册观察者,来观察keyPath的变化
  2. 当相对于被观察对象的指定键路径的值发生变化时,通知观察对象的observeValueForKeyPath:ofObject:change:context:这个方法,观察者应当实现该方法
  3. 当不再需要观察对象属性变化时,通过调用removeObserver:forKeyPath:或者removeObserver:forKeyPath:context:阻止观察者对象接收与接收此消息的对象相关的键路径指定的属性的更改通知.

注:addObserverremoveObserver应当一一对应

注册方法

在注册时,options的值为NSKeyValueObservingOptions枚举类型
。当为NSKeyValueObservingOptionNewNSKeyValueObservingOptionOld时,表示接收新值和旧值,默认为只接收新值。如果想在注册观察者后,立即接收一次回调,则可以加入NSKeyValueObservingOptionInitial枚举

实现原理

KVO是通过isa-swizzling技术实现的。在运行时根据原类创建一个中间类,这个中间类是原类的子类,并动态修改当前对象的isa指向中间类。并且将class方法重写,返回原类的Class。所以苹果建议在开发中不应该依赖isa指针,而是通过class实例方法来获取对象类型。

验证

` _stu = [Student new];
  _stu.stu_id = index;
  NSLog(@"beforeClass:%@",  object_getClass(_stu));
 [_stu addObserver:self forKeyPath:@"age"    options:NSKeyValueObservingOptionNew context:nil];
 NSLog(@"afterClass:%@", object_getClass(_stu));`

可以查看输出结果为:

`2018-12-30 14:34:01.761066+0800 KVO[1485:239369]           beforeClass:Student`

2018-12-30 14:34:01.761533+0800 KVO[1485:239369] afterClass:NSKVONotifying_Student

自定义KVO

写一个Student的分类

Student+KVO.h

 `-(void)XK_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;`

Student+KVO.m

#import "NSObject+KVO.h"
#import <objc/runtime.h>
#import <objc/message.h>
@implementation Student  (KVO)
-(void)XK_addObserver:(NSObject *)observer  forKeyPath:(NSString *)keyPath options: (NSKeyValueObservingOptions)options context:(void *)context{
NSString* oldClassName = NSStringFromClass([self class]);
NSString* newClassName = [@"XKKVONotyfing_" stringByAppendingString:oldClassName];
const char * newName = [newClassName UTF8String];
Class newClass = objc_allocateClassPair([self class], newName, 0);
class_addMethod(newClass,@selector(setAge:), (IMP)setAge, "v@:i");
objc_registerClassPair(newClass);
object_setClass(self, newClass);
objc_setAssociatedObject(self,          
(__bridge const void *)@"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}

void setAge(id self, SEL _cmd, int age) {
Class myClass = [self class];
object_setClass(self, class_getSuperclass([self class]));
//调用父类
id (*msgSend) (id, SEL,...) = (void *)objc_msgSend;
msgSend(self, @selector(setAge:),age);
id observer = objc_getAssociatedObject(self, (__bridge const void *)@"objc");
 id (*msgSendObj) (id, SEL,id,...) = (void *)objc_msgSend;
   msgSendObj(observer,@selector(XK_observeValueForKeyPath:ofObject:change:context:),@"age",@"age",nil,nil);
//改为子类
object_setClass(self, myClass);
}

观察者中调用

<[_stu XK_addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];

- (void)XK_observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary)change context:(void *)context{
 NSLog(@"keyPath:%@",keyPath);
 NSLog(@"ofObject:%@",object);
 NSLog(@"change:%@",change);
 NSLog(@"afterClass:%@", object_getClass(_stu));
}</code></pre>
目录
相关文章
|
6月前
|
安全 Swift iOS开发
【Swift开发专栏】Swift中的属性观察者与KVO
【4月更文挑战第30天】Swift编程语言支持属性观察者(`willSet`和`didSet`)和键值观察(KVO)来响应属性变化。属性观察者在设置前(`willSet`)和设置后(`didSet`)执行代码,可用于数据绑定。KVO是Cocoa/Cocoa Touch中的机制,需`NSObject`子类和`@objc dynamic`属性配合使用。注意在观察者销毁前移除观察,以避免内存问题。示例展示了属性观察者实现简单数据绑定。
77 1
开门小例子学习观察者模式&事件与委托
3.2.一个喊话人(喊话人有权限),多个拿钥匙开门的人(每个人负责不同的门):米老师大喊给我开一下水麒麟的门——>此时听到消息并且拿着水麒麟钥匙的人就会过来开门
|
前端开发 Java API
对象状态分析|学习笔记
快速学习对象状态分析
|
Android开发 iOS开发
iOS开发:KVC与KVO
KVC 就是键值编码(key-value-coding),可以直接访问对象的属性,或者给对象的属性赋值。黑魔法之一,很多高级的iOS开发技巧都是基于KVC实现的。 KVO 是键值观察者(key-value-observing)。实现方式:通过对某个对象的某个属性添加观察者,当该属性改变,就会调用”observeValueForKeyPath:”方法,为我们提供一个“对象值改变了!”的时机进行一些操作。
241 0
iOS开发:KVC与KVO
|
架构师 开发者 iOS开发
探究ReactiveCocoa 底层KVO封装流程
一、对比原生KVO,初识ReactiveCocoa的KVO * 我们先来看一段代码,通过触屏来动态修改视图背景色 @interface ViewController () @property (nonatomic, strong)UIColor * bgColor; @end @implemen...
3119 0
KVO 解析
KVO解析(一) —— 基本了解KVO解析(二) —— 一个简单的KVO实现KVO解析(三) —— KVO合规性KVO解析(四) —— Faults and KVO Notifications
841 0