美文网首页
iOS KVO的使用和原理及自定义

iOS KVO的使用和原理及自定义

作者: J扣歪 | 来源:发表于2019-06-18 16:22 被阅读0次

一  观察者与被观察者之间的关系

观察者self强引用被观察者p,但是被观察者p并不强引用self否则将会造成循环引用.当self被释放了,p拿不到self,但p的属性name仍然可能会被赋值所以observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionaryid> *)change context:(void*)context这个方法仍然可能会被调用而此时self已经被释放了.为了防止这种现象所以要在 delloc里面移除观察者.

二  KVO触发条件

1.

如图在Person类中重写+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key方法,如果返回NO,KVO为手动触发模式如果返回YES则为自动触发模式. key为受到改变的Person类的属性.这里将改变name时设置为手动触发模式

2.

在赋值前添加 [_p willChangeValueForKey:NSStringFromSelector(@selector(name))]; 意为即将做出改变,在赋值后添加[_p didChangeValueForKey:NSStringFromSelector(@selector(name))]; 意为已经做出改变.这两个方法为手动模式触发的条件. 设置完后触发touchesBegan可以看到控制台输出,监听成功.

3.

若此时我们不添加给属性name的赋值方法,通过控制台打印发现kvo仍可以被触发.说明KVO触发与属性赋值无关但与willChangeValueForKey及didChangeValueForKey这两个方法的调用有关.

三 属性依赖

给Person类新建一个类属性friends

给Person类新建一个类属性friends并且观察这个属性,通过touchesBegan改变friends的num及age属性.发现并未触发kvo.因为我们观察的是friends属性而不是_friends.age,那么如何才能在改变friends的属性时也能触kvo模式呢?

在person类里重写+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString*)key方法.这里返回的key是我们所观察的person的属性.通过判断当key为friends时返回一个集合,集合里就放入我们所想观察变化的属性如:_friends.age和_friends.num

再次改变person的属性,通过控制台打印发现kvo可以被触发.

四  自定义KVO

1.  开发中若想一直操作某个类的属性改变的地方有两种:1.在分类中重写属性setter方法 2.通过子类继承重写父类属性的setter方法(注:子类并不拥有父类属性而是可以调用父类方法). 但是如果我们按照方法1的话就覆盖原来的setter方法造成我们原有setter方法中的操作不被执行,所以方法2是一个很好的选择.那么KVO实现的原理会不会也是这样呢?

,

如图可以看到在执行了[_p addObserver:self forKeyPath:@"friends" options:(NSKeyValueObservingOptionNew) context:nil];这句代码后,通过lldb调试发现原来的person对象_p的isa指针不再指向person类而是NSKVONotifying_Person这个类.

2.  添加一个分类NSObject+KVO.h并仿照系统方法给分类添加一个方法DIY_addObserver:(NSObject*)observer forKeyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context;在这个方法中我们新建了一个类继承于self也就是被观察者,并给这个类添加了一个setName方法相当于其父类中的setter方法.并且将被观察者的isa指针指向这个新类(isa指针指向谁,调用方法的就是谁),如此当被观察者调用setName方法时将会执行新类的setName方法(注意这里的方法名称一定是相同的).再在setName方法中给观察者observe的observeValueForKeyPath:ofObject:change:context:这个方法发送消息如此自定义的观察者就实现了! 直接使用对象调用给分类添加的这个方法即可.

五  容器类观察

给person类添加一个数组array并且观察这个数组的变化,若直接调用_p对象的array属性的addObject方法是无法触发监听者模式的,此时kvo提供了一个方法通过mutableArrayValueForKey获取可变数组并且通过改变这个数组即可触发kvo. 再次通过lldb调试又发现arrays指向了NSKeyValueNotifyingMutableArray这个类,那么KVO会不会又创建了一个继承NSMutableArray的子类NSKeyValueNotifyingMutableArray,再通过重写这个子类的addObject方法实现了监听呢?

相关文章

  • iOS-底层原理-自定义KVO

    1.自定义KVO 1.上一篇博客了解了iOS 系统KVO的底层实现原理,那么这里进行自定义KVO,更好的理解原理和...

  • KVO基本使用

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

  • iOS KVO的使用和原理及自定义

    一 观察者与被观察者之间的关系 观察者self强引用被观察者p,但是被观察者p并不强引用self否则将会造成循环引...

  • iOS KVO机制的基本使用及实现原理

    我用#CSDN#《iOS KVO机制的基本使用及实现原理》 https://blog.csdn.net/u0112...

  • KVC/ KVO

    1、kvc原理: 45页 2、自定义KVO KVO参考链接 KVO默认观察setter,使用isa-swizzli...

  • KVO和KVC的使用及原理解析

    一 KVO基本使用 二 KVO本质原理讲解及代码验证 三 KVC基本使用 四 KVC设值原理 五 KVC取值原理 ...

  • iOS底层学习文章

    iOS黑魔法-Method Swizzling Objective-C 反射机制 KVC原理剖析 KVO原理分析及...

  • 底层原理

    iOS底层原理总结 - Category的本质 KVO详解及底层实现青少年一定要读的KVO指南 iOS 底层解析w...

  • 面试题整理

    KVO原理及自定义KVO KVO原理我们注册监听的时候,会对注册者动态的创建一个子类对象,然后底层找方法的的isa...

  • iOS-自定义KVO

    KVO原理及使用 我们之前讨论过KVO的原理,知道KVO机制是生成了一个中间类NSKVONotifying,该中间...

网友评论

      本文标题:iOS KVO的使用和原理及自定义

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