• KVOController原理解析


    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

  • 相关阅读:
    oracle归档空间不足的问题(rman删除归档日志)
    oracle DG查看延时时间
    Convert JS object to JSON string
    转:微信公众平台开发(80) 上传下载多媒体文件
    生成带参数的二维码
    关闭微信浏览器可以使用
    微信内置浏览器的JsAPI(WeixinJSBridge续)进入全屏
    如何隐藏微信公众平台右上角按钮
    微信公众平台服务号、订阅号的相关说明选择字号:
    微信公众平台群发消息的方法及注意事项
  • 原文地址:https://www.cnblogs.com/feng9exe/p/10432759.html
Copyright © 2020-2023  润新知