KVO 实现原理

KVO 实现原理

KVO即Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。

KVO的原理

  1. 当一个object有观察者时,动态创建这个object的类的子类
  2. 对于每个被观察的property,重写其set方法
  3. 在重写的set方法中调用- willChangeValueForKey:和- didChangeValueForKey:通知观察者
  4. 当一个property没有观察者时,删除重写的方法
  5. 当没有observer观察任何一个property时,删除动态创建的子类

当我们在添加观察者的时候,打一个断点,在设置属性的时候打一个断点

KVO 实现原理_第1张图片
KVO 实现原理_第2张图片

发现对象P的isa指针居然变量了,指向的类也不是我们自己创建的,那也就说明是系统自己创建的,Person类的子类NSKVONotifying_Person,并且重写了set方法。其实,就是去判断有没有调用一个对象的set方法

现在我们就手动的模拟下这种情况

首先我们需要创建一个NSObject的分类,创建自己添加观察者的方法

@interface NSObject (KVO)
- (void)xf_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
@end

#import "NSObject+KVO.h"
#import 
#import "XFKVONotifying_Person.h"

@implementation NSObject (KVO)

- (void)xf_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context {

    // 修改isa,改变当前对象的类名
    object_setClass(self, [XFKVONotifying_Person class]);

    //添加关联,把观察者保存到当前对象里
    objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

@end

由于我们使用了运行时,所以别忘记导入

我们还需要创建一个 XFKVONotifying_Person类,并继承于 Person

#import "Person.h"

@interface XFKVONotifying_Person : Person

@end

#import "XFKVONotifying_Person.h"
#import 

@implementation XFKVONotifying_Person

-(void)setAge:(NSInteger)age {

    [super setAge:age];

    //取出观察者,并通知观察者属性改变
    id observer = objc_getAssociatedObject(self, @"observer");
    
    [observer observeValueForKeyPath:@"age" ofObject:self change:nil context:nil];

}

@end

最后我们调用自己写的方法:

[p xf_addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];

一样可以观察到属性值的变化

总结

KVO底层实现原理:

  1. 动态创建NSKVONotifying_Person,NSKVONotifying_Person是Person子类,做KVO
  2. 修改当前对象的isa指针->NSKVONotifying_Person
  3. 只要调用对象的set,就会调用NSKVONotifying_Person的set方法
  4. 重写NSKVONotifying_Person的set方法:
  • [super set:]
  • 通知观察者,告诉你属性改变

你可能感兴趣的:(KVO 实现原理)