美文网首页
KVO的浅显理解

KVO的浅显理解

作者: FallLeaf | 来源:发表于2018-11-20 23:23 被阅读0次

近两天看视频教程,粗略的学习了一下KVO的使用。做个笔记,以便后期自己查阅。
KVO的实质则是通过iOS的runtime来动态的创建监听类的子类,重写子类对象的setter方法。在setter方法中发送通知。

KVO的使用

//添加观察者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
//移除观察者
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context

这两个方法一定是成对出现的。添加后,在dealloc中要将添加的观察者移除。
简述下添加方法的参数含义:
1.observer代表的是监听者。
2.keyPath指的是监听属性的名称。
3.options有四种

  • NSKeyValueObservingOptionNew 传回新值。
  • NSKeyValueObservingOptionOld 传回旧值。
  • NSKeyValueObservingOptionInitial 注册的时候发送一次通知,监听对象的值发生改变的时候也会发送一次通知。
  • NSKeyValueObservingOptionPrior 监听的对象值发生改变之前发一次,改变之后发一次。

KVO的手动和自动发送通知方法

这个方法写在监听类中。在这个方法里我们可以根据监听对象的key值来判定是要返回YES还是NO。默认为YES。

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key

KVO的属性依赖

例如我们监听一个Person类,Person类里面有个Dog类的对象dog。Dog有age和level两个属性。那现在我们要如何监听dog里面的属性的变化呢?

首先我们在控制器中添加观察者

[_person addObserver:self forKeyPath:@"dog" options:NSKeyValueObservingOptionNew context:nil]

在Person类中重写属性依赖的方法

+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
    if ([key isEqualToString:@"dog"]) {
        keyPaths = [[NSSet alloc] initWithObjects:@"_dog.age",@"_dog.level", nil];
    }
    return keyPaths;
}

这样子我们就完成了对于Person类中dog属性变化的监听。

KVO的实质及自定义KVO

KVO的实质

那么最开始我们讲到,KVO的实质就是通过iOS的runtime来动态创建监听类的子类,然后重写子类的setter方法,这边我们再详细的说明一下。
首先我们来看一下,Person类在添加KVO前后的isa指针的变化。


我们在给_person对象添加KVO的地方打了个断点,查看到当前_person的isa指针是指向Person这个类的。

)
再来看一下添加_person添加KVO之后的isa指针是指向什么。


_person添加KVO之后的isa指针指向
通过两张图我们很明显的看到,_person对象在添加KVO前后的isa指针指向是不同的,这是怎么回事呢?道理很简单,在_person添加KVO的时候,系统就会通过runtime动态的去创建一个Person的子类,也就是NSKVONotifying_Person这个类,也同时的改变的_person的isa指针指向。

自定义KVO

这边自己按照视频教程写了一个自定义的KVO。创建一个NSObject的分类,在分类里面自定义一个添加KVO的方法。

- (void)Leaf_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context {
    //1.自定义NSKVONotifying_Person子类
    NSString *oldClassName = NSStringFromClass(self.class);
    NSString *newClassName = [NSString stringWithFormat:@"LeafKVONotifying_%@",oldClassName];
    
    //创建一个类
    Class myClass = objc_allocateClassPair(self.class, newClassName.UTF8String, 0);
    
    //注册创建的类
    objc_registerClassPair(myClass);
    
    //2.动态的修改调用者的类型
    object_setClass(self, myClass);
    
    //3.添加setName方法 重写父类的setName
    class_addMethod(myClass, @selector(setName:), (IMP)setName, "V@:@");
}

void setName(id self, SEL _cmd, NSString *nerName) {
    //修改name属性
    //通知外界 willChange didChange
}

最终重写setter的方法里面没有完全的实现。后续会补充完整。这里面就是利用消息机制给这个方法发送通知,这样我们就能在这个方法里面收到属性变化后的通知。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context

总结

以上就是我自己对于KVO学习之后的一些理解。后续还有一些关于KVO对于容器类监听的理解,会慢慢补充。还有很多不足之处,一起学习,共勉。

相关文章

  • KVO的浅显理解

    近两天看视频教程,粗略的学习了一下KVO的使用。做个笔记,以便后期自己查阅。KVO的实质则是通过iOS的runti...

  • 浅显的理解

    更新600天了,前面两张卡用了以后,后面就没有断了,虽然不是什么大不了的事情,但是坚持去做之后,还是有很多收获的,...

  • KVO基本使用

    分三部分解释KVO一.KVO基本使用二.KVO原理解析三.自定义实现KVO 一、KVO基本使用 使用KVO,能够非...

  • IOS KVO原理解析与应用

    IOS KVO原理解析与应用 一、KVO概述 KVO,即:Key-Value Observing,是Objecti...

  • 理解KVO

    相信KVO对大家来说都不陌生,即使你没有使用过,基本也都曾了解过,听说过。这篇文章作者就带大家来深入研究一下KVO...

  • delegate和notification区别,分别在什么情况下

    KVC(Key-Value-Coding)KVO(Key-Value-Observing)理解KVC与KVO(键-...

  • KVO详解及底层实现

    什么是KVO?? KVO就是NSKeyValueObserving,请看官方文档的解释: 大概翻译如下: 简单理解...

  • KVO 的总结

    kvo 1.kvo介绍 KVO是一种允许对象在其他对象的指定属性发生变化时被通知的机制。 重点:为了理解KVO,首...

  • 透彻理解 KVO 观察者模式(附基于runtime实现代码)

    透彻理解 KVO 观察者模式(附基于runtime实现代码) 透彻理解 KVO 观察者模式(附基于runtime实...

  • 谈谈《活法》的浅显理解

    《活法》,由稻盛和夫著写的。我感觉到了这本书的深邃之处,是一本值得花很长时间来慢慢体会的好书。 今天的我阅读这本书...

网友评论

      本文标题:KVO的浅显理解

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