zoukankan      html  css  js  c++  java
  • iOS 自动移除KVO观察者

    对NSObject写一个分类:

    #import <Foundation/Foundation.h>

    @interface NSObject (FMObserverHelper)

    - (void)fm_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

    @end

    //  对象被释放之前, 会调用dealloc方法, 其持有的实例变量也会被释放.

    //  在监听注册时, 为self和Observer关联个临时对象, 当两者在释放实例变量时, 借助这个时机, 在临时对象的dealloc方法中, 移除Observer

    //  self在被释放之前, 会先释放其持有的关联属性, self并未完全释放, 可在临时对象中target却成了nil.

    //  weak: 持有者不会对目标进行retain, 当目标销毁时, 持有者的实例变量会被置空

    //  unsafe_unretained: 持有者不会对目标进行retain, 当目标释放后, 持有者的实例变量还会依然指向之前的内存空间(野指针)

    //  如果Observer提前释放,而添加关联属性, 两者还不能同时持有临时对象, 否则临时对象也不会及时的释放,既然一个不行, 那就各自关联一个.

    //  两个关联属性释放的同时, 进行了两次观察移除的操作. 为避免这个问题, 需要判断weak引用的实例变量factor是否为空即可

    #import "NSObject+FMObserverHelper.h"

    #import <objc/runtime.h>

    @interface FMObserverHelper : NSObject

    @property (nonatomic, unsafe_unretained) id target;

    @property (nonatomic, unsafe_unretained) id observer;

    @property (nonatomic, strong) NSString * keyPath;

    @property (nonatomic, weak) FMObserverHelper * factor;

    @end

    @implementation FMObserverHelper

    - (void)dealloc {

        if ( _factor ) {

            [_target removeObserver:_observer forKeyPath:_keyPath];

        }

    }

    @end

    @implementation NSObject (FMObserverHelper)

    - (void)fm_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath {

        [self addObserver:observer forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:nil];

        

        FMObserverHelper * helper = [FMObserverHelper new];

        FMObserverHelper * sub = [FMObserverHelper new];

        

        sub.target = helper.target = self;

        sub.observer = helper.observer = observer;

        sub.keyPath = helper.keyPath = keyPath;

        helper.factor = sub;

        sub.factor = helper;

        

        const char * helpeKey = [NSString stringWithFormat:@"%zd", [observer hash]].UTF8String;

        objc_setAssociatedObject(self, helpeKey, helper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

        objc_setAssociatedObject(observer, helpeKey, sub, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    @end

  • 相关阅读:
    ps 允许执行不信任的脚本
    mysql 某表某列支持 emoji
    jenkins
    成为真正的win10 超级管理员,解决win+r 不以管理员身份运行
    bat curl 定时请求
    jq 日期区间处理
    jq 日期区间处理
    ubuntu cli
    nginx启动两个flask项目
    nginx 配置http和https验证
  • 原文地址:https://www.cnblogs.com/fengmin/p/8125870.html
Copyright © 2011-2022 走看看