设为首页 加入收藏

TOP

【OC底层】KVO原理(三)
2019-08-31 00:22:09 】 浏览:72
Tags:底层 KVO 原理
ing_XGPerson.h
" // KVO的原理伪代码实现 @implementation NSKVONotifying_XGPerson - (void)setAge:(int)age{ _NSSetIntValueAndNotify(); } - (void)_NSSetIntValueAndNotify{ // KVO的调用顺序 [self willChangeva lueForKey:@"age"]; [super setAge:age]; // KVO会在didChangeva lueForKey里面调用age属性变更的通知回调 [self didChangeva lueForKey:@"age"]; } - (void)didChangeva lueForKey:(NSString *)key{
// 通知监听器,某某属性值发生了改变 [oberser observeva lueForKeyPath:key ofObject:self change:nil context:nil]; } // 会重写class返回父类的class // 原因:1.为了隐藏这个动态的子类 2.为了让开发者不那么迷惑 - (Class)class{ return [XGPerson class]; } - (void)dealloc{ // 回收工作 } - (BOOL)_isKVOA{ return YES; }

 

如何手动调用KVO

其实通过上面的代码大家已经知道了KVO是怎么触发的了,那怎么手动调用呢?很简单,只要调用两个方法就行了,如下:

 

    [self.person1 willChangeva lueForKey:@"age"];
    [self.person1 didChangeva lueForKey:@"age"];

但是上面说调用顺序的时候,好像明明KVO是在 didChangeVlaueForKey 里面调用的,为什么还要调用 willChangeVlaueForKey呢?

那是因为KVO调用的时候会去判断这个对象有没有调用 willChangeVlaueForKey 只有调用了这个之后,再调用 didChangeVlaueForKey 才能真正触发KVO

直接修改成员变量会触发KVO吗?

答案是不会的,为什么呢?因为KVO是通过修改set方法实现来触发的,一个成员变量都没有 set 方法,所以肯定是不会触发了.

总结

KVO是通过runtime机制动态的给要添加KVO监听的对象创建一个子类,并且让instance对象的isa指向这个全新的子类.

当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数,顺序如下:

  • willChangeva lueForKey:
  • 父类原来的setter
  • didChangeva lueForKey:

didChangeva lueForKey 内部会触发监听器(Oberser)的监听方法( observeva lueForKeyPath:ofObject:change:context:)

通过这个子类重写一些父类的方法达到触发KVO回调的目的.

 

补充

KVO是使用了典型的发布订阅者设计模式实现事件回调的功能,多个订阅者,一个发布者,简单的实现如下:

1> 订阅者向发布者进行订阅.

2> 发布者将订阅者信息保存到一个集合中.

3> 当触发事件后,发布者就遍历这个集合分别调用之前的订阅者,从而达到1对多的通知.

 

以上已全部完毕,如有什么不正确的地方大家可以指出~~ ^_^ 下次再见~~

  

首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇iOS开发之OC与swift开发混编教程.. 下一篇给button增加下划线

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目