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

最新文章

  1. 搭建S3C6410开发板的测试环境
  2. shell流程控制&函数
  3. CentOS 安装
  4. SQL笔记-第三章,数据的增删改
  5. Windows Server 2008 显示桌面图标
  6. TCP/IP协议原理【转载】
  7. Linux下如何查找可执行文件
  8. Tile-Based Deferred Rendering
  9. [Leetcode] Merge Sorted Array (C++)
  10. db2迁移至oracle过程中的问题
  11. CBC之php java兼容版本
  12. Android为TV端助力转载:码农小阿飞(SpannableString)
  13. lambda-基于谓词筛选值序列
  14. JumpServer里的sftp功能报错说明
  15. Adobe Premiere Pro CC ------ 快捷键
  16. python中使用tabula爬取pdf数据并导出表格
  17. postfix发信提示 Error: too many connectino from
  18. keras的训练引擎:train_array.py和train_generator.py
  19. 使用Jquery实现Win8开始菜单效果的站点导航
  20. Android -- 加载大图片的方法

热门文章

  1. 插入sql返回主键id
  2. C#设计模式六大原则——接口隔离
  3. 基于socket的简单p2p聊天项目
  4. linux系统下开启一个简单的web服务
  5. javaSE——字节流
  6. python之定义函数
  7. <Android 基础(二十八)> Fragment (1)
  8. OpenGL学习--08--基本渲染(灯光)
  9. 强网杯2018 pwn复现
  10. idea 自动导入包设置