美文网首页
KVO-基本实现

KVO-基本实现

作者: SK丿希望 | 来源:发表于2018-11-28 12:55 被阅读0次

定义1个类父类继承NSObject

@interface A : NSObject
@property (nonatomic, strong) id obj;
@end

@implementation A
- (instancetype)init {
    self = [super init];
    if (self) {
        self.obj = @"defaulf";
    }
    return self;
}
@end

定义一个子类继承A

@interface B : A

@end
@implementation B
- (void)setObj:(id)obj {
    super.obj = obj;
    NSLog(@"子类来了");
}
@end

在控制器中对子类B进行监听obj的改变

@interface ViewController ()
@property(nonatomic, strong) B *b;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.b = [[B alloc] init];
    [self.b addObserver:self forKeyPath:@"obj" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    self.b.obj = @"hello";
}
- (void)dealloc {
    [self.b removeObserver:self forKeyPath:@"obj"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"%@--%@--%@", [self class], object, change);
    
    NSLog(@"%@", [change objectForKey:NSKeyValueChangeNewKey]);
    NSLog(@"%@", [change objectForKey:NSKeyValueChangeOldKey]);
}
@end

图标1:是创建B继承父类方法 对B进行初始化的时候也给obj进行赋值
图标2:是点击屏幕是修改obj是进去的

image.png

总结:其实又上面可以看出来KVO其实是对监听属性的set方法进行了某些处理

简单概述下 KVO 的实现:

当你观察一个对象时,一个新的类会动态被创建。这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法。自然,重写的 setter 方法会负责在调用原 setter方法之前和之后,通知所有观察对象值的更改。最后把这个对象的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例。
原来,这个中间类,继承自原本的那个类。不仅如此,Apple 还重写了 -class 方法,企图欺骗我们这个类没有变,就是原本那个类。

使用注意:

[self.b addObserver:`self` forKeyPath:@"obj" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL];

在以上方法中其实添加观察,并不会对self进行强引用(即不会对其引用计算器进行+1),但是为什么我们往往需要在dealloc析构中,删除对其的监听了,原因为啥???

dealloc析构中,删除对其的监听原因

其实原因很简单:和KVO的特性有关,KVO主要是一对多,不像代理的一对一,只要添加了观察后,只要观察的内容进行改变都会来的对应的- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context方法,如果在这个方法中引用了self,那么如果当前类已经释放调了,因为之前添加过观察,当监听的值改变后,都会来到- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context,当前对象已经被释放了,调野指针,程序直接崩溃,故需要在dealloc析构中,删除对其的监听


因为B是继承A的本身是没有obj这个属性的 下图可以看出其实这个属性是A的


image.png

相关文章

  • KVO-基本实现

    定义1个类父类继承NSObject 定义一个子类继承A 在控制器中对子类B进行监听obj的改变 图标1:是创建B是...

  • KVC\KVO-代理-通知-整理中

    KVC\KVO-代理-通知

  • KVC和KVO-基本用法

    (一)KVC 通过键或者键值路径读写值 通过键取值- (nullable id)valueForKey:(NSSt...

  • KVO的实现原理

    KVO的实现原理 KVO-键值观察机制,原理如下: 1.当给A类添加KVO的时候,runtime动态的生成了一个子...

  • 利用runtime自己动手实现KVO- 简书

    昨天开始学习runtime写下做个记录,利用runtime实现系统的KVO,首先我们先来看一下系统的实现,首先定义...

  • KVO-监听属性值

    简介 KVO全称KeyValueObserving,俗称键值监听,是苹果提供的一套事件通知机制。允许对象监听另一个...

  • iOS -KVO

    KVO-键值观察 KVC:对象取值或者设置值。KVO:监听对象值的变化。 响应式编程的一种。KVO的使用非常简单,...

  • KVO-容器类的观察

    1.KVO对Array的观察。 我们平时对于对象的属性进行KVO的观察时,都是需要观察变化的对象调用addObse...

  • 工厂方法设计模式

    一、UML 二、基本步骤 2.1、工厂基本抽象类实现 2.2、产品基本抽象类实现 2.3、工厂业务实现 2.4、产...

  • 数据结构--链表

    基本概念 实现方式 基本操作

网友评论

      本文标题:KVO-基本实现

      本文链接:https://www.haomeiwen.com/subject/litaqqtx.html