1、使用类似动态代理的模式和消息派发中枢模式实现整个架构;

2、使用NSMapTable和NSHashTable进行切面信息的增删查维护;主要用于去重和查看是否存在。

实现方式

消息流

KVOControllerKVOControllerUML

observer 调用的方法注册观察者。

  • FBKVOController 处理观察者信息,并将其封装为_FBKVOInfo。过滤重复的或者未注册过的观察消息。定义如下:
    @interface _FBKVOInfo : NSObject
  • @end
  • @implementation _FBKVOInfo {
  • @public
  • __weak FBKVOController *_controller;
  • NSString *_keyPath;
  • NSKeyValueObservingOptions _options;
  • SEL _action;
  • void *_context;
  • FBKVONotificationBlock _block;
  • }
  • _FBKVOInfo FBKVOController _FBKVOInfo _FBKVOInfo crashFBKVOController 调用中转站的方法。
  • _FBKVOSharedController 向完成真正的观察者注册。
  • 关注的发生改变时,向发送通知。
  • _FBKVOSharedController _FBKVOInfo observerobserver 与为一一对应关系,即一个观察者实例对应一个实例,而所有的观察者注册和回调工作都有这个单例完成,其将在软件的整个生命周期内存活。

    弱引用

    KVOController @interface FBKVOController : NSObject

    @property (atomic, weak, readonly) id observer;

    @end

    @implementation FBKVOController

    - (void)dealloc {

    [self unobserveAll];

    }

    @end

    KVOController 维护了一个对观察者的弱引用。

  • KVOController 释放时会移除其注册的观察者消息。

_FBKVOInfo FBKVOController KVOController KVOController KVOController 消息过滤

KVOController 如下所示,为 FBKVOController 的 observe 代码片段,通过可知,首先判断是否已经包含对应观察者消息,如果包含则直接返回。

- (void)_observe:(id)object info:(_FBKVOInfo *)info {

OSSpinLockLock(&_lock);

NSMutableSet *infos = [_objectInfosMap objectForKey:object];

_FBKVOInfo *existingInfo = [infos member:info];

if (nil != existingInfo) {

NSLog(@"observation info already exists %@", existingInfo);

OSSpinLockUnlock(&_lock);

return;

}

且内部采用NSMapTable 作为容器存储被观察者和对应的观察者信息,类似于,但更加灵活和强大,支持添加指针、以及对象等,即允许指定加入容器中项的内存管理方式和类型行为,比如可以指定内存管理方式采用、和中的一种,还可以设定加入项的相等判断方式,比如指针或者方法。类似的容器还有和,分别对应于和。

中的构造方式如下:

NSPointerFunctionsOptions keyOptions = retainObserved ? NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPointerPersonality : NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality;

_objectInfosMap = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPersonality capacity:0];

根据传入参数可以决定是否对被观察者维持一个强引用,对等的详细解释参考Pointer Function Options。表示对加入的项维持强引用,则相反。而通过指针判断加入的项是否相等,则通过加入对象的方法判断。其中为被观察者,为实例,也即观察者消息信息。

KVOController通过提供 _FBKVOSharedController 注册和转发消息,避免观察者直接使用 kvo,通过这个中间层达到了隔离的效果。并且提供一个跟观察者一一对应的 FBKVOController,过滤掉容易出错的注册和移除消息的请求,且 FBKVOController 生命周期跟观察者绑定,则观察者释放时,由 FBKVOController 生成的实例也被释放,从 _FBKVOSharedController 移除对应的观察者信息,避免发消息给已释放观察者导致的crash。

http://www.cnblogs.com/CoderPlace/p/4624229.html

KVOController原理解析的更多相关文章

  1. [原][Docker]特性与原理解析

    Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...

  2. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

  3. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  4. Web APi之过滤器创建过程原理解析【一】(十)

    前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...

  5. GeoHash原理解析

    GeoHash 核心原理解析       引子 一提到索引,大家脑子里马上浮现出B树索引,因为大量的数据库(如MySQL.oracle.PostgreSQL等)都在使用B树.B树索引本质上是对索引字段 ...

  6. alibaba-dexposed 原理解析

    alibaba-dexposed 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49821413 原理参考地址: htt ...

  7. 支付宝Andfix 原理解析

    支付宝Andfix 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49802429 原理参考地址: http://blo ...

  8. JavaScript 模板引擎实现原理解析

    1.入门实例 首先我们来看一个简单模板: <script type="template" id="template"> <h2> < ...

  9. Request 接收参数乱码原理解析三:实例分析

    通过前面两篇<Request 接收参数乱码原理解析一:服务器端解码原理>和<Request 接收参数乱码原理解析二:浏览器端编码原理>,了解了服务器和浏览器编码解码的原理,接下 ...

随机推荐

  1. MyEclipse中快速查看错误

    当代码中有错误的时候,MyEclipse会用红线标示错误.这个时候在错误地方按下F2就会显示错误详情了.

  2. 实现一个符合 RESTful 架构的程序

    前言:在网上经常看到 RESTful,十分好奇,于是自己来试试. 代码地址:https://github.com/yuleGH/restdemo 首先,介绍一下 RESTful 架构:理解 RESTf ...

  3. python学习之老男孩python全栈第九期_第二周学习总结

    迭代器 双下方法:很少直接调用的方法,一般情况下,是通过其他语法触发的 1. 可迭代的 --> 可迭代协议:含有__iter__的方法( '__iter__' in dir(数据) ) 可迭代的 ...

  4. 基于Vue实现图片在指定区域内移动

    当图片比要显示的区域大时,需要将多余的部分隐藏掉,我们可以通过绝对定位来实现,并通过动态修改图片的left值和top值从而实现图片的移动.具体实现效果如下图,如果我们移动的是div 实现思路相仿. 此 ...

  5. html-图像标签

    图像标签 <img src="图片的路径"/> -src:图片的路径 -width:图片的宽度 -height:图片的高度 -alt:图片上显示的文字,把鼠标移动到图片 ...

  6. Thymeleaf模板表达式

    日期格式.组件提取等. ${#dates.format(date)}${#dates.arrayFormat(datesArray)}${#dates.listFormat(datesList)}${ ...

  7. Myeclipse打war包方法

    Myeclipse三种打包方法第一种方法打开Myeclipse如图操作. 如果该项目已存在需要移除之后在进行第三步,接着往下走. 项目打war包成功,推荐使用第一种方法. 第二种方法https://b ...

  8. Collection FrameWork

    Collection FrameWork如下: Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashta ...

  9. Python 底层原理知识

    1.Python是如何进行内存管理的? 答:从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制 一.对象的引用计数机制 Python内部使用引用计数,来保持追踪内存中的对象,所有对象都 ...

  10. 网络I/O模型--05多路复用I/O

    多路复用I/O模型在应用层工作效率比我们俗称的 BIO 模型快的本质原因是,前者不再使用操作系统级别的“同步 I/O”模型 . 在 Linux 操作系统环境下, 多路复用 I/O 模型就是技术人员通常 ...