对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

iOS 自动移除KVO观察者的更多相关文章

  1. IOS学习之初识KVO

    什么是KVO? KVO(Key-Value Observing)键值观察,是一种通过对对象的某一个属性添加观察者,一旦这个属性值发生变化,就会通知当前观察者的一种机制. 该如何使用? 1.注册,指定被 ...

  2. CVS 文件自动移 tag 的 Python 脚本

    CVS 文件自动移 tag 的 Python 脚本 背景 工作中使用的版本管理工具是 CVS,在两次发布中,如果修改的文件比较少,会选择用移 Tag 的方式来生成一个新 Tag 发布.文件比较少的情况 ...

  3. iOS NSNotificationCenter 移除通知带来的crash

    Where to remove observer for NSNotification? 在dealloc方法中移除通知观察者带来crash NSNotificationCenter中的通知消息已经发 ...

  4. ios自动打包-fastlane 安装、使用、更新和卸载

    ios自动打包使用fastlane 1.首先安装xcode 首先检查是否已经安装 Xcode 命令行工具,fastlane 使用 xcodebuild 命令进行打包,运行 xcode-select - ...

  5. 40、IOS自动打包-Python脚本

    第一种:基于编译的打包 编译工程--找到.app文件--新建Payload文件夹--拷贝.app到Payload文件夹--压缩成zip--更改后缀名为ipa--完成! 第二种(有问题,暂时不需要看) ...

  6. ios - kvo观察者示例

    首先创建Person分类 #import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatom ...

  7. 【原】iOS中KVC和KVO的区别

    在iOS开发中经常会看到KVC和KVO这两个概念,比较可能混淆,特地区分一下 KVC(Key Value Coding) 1> 概述 KVC:Key Value Coding,键值编码,是一种间 ...

  8. iOS 中KVC、KVO、NSNotification、delegate 总结及区别-b

    1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的 ...

  9. 【iOS】KVC 与 KVO

    一.KVC与KVO *"KVC":key value Coding(键值编码) *目的:间接的改动或获取对象的属性,减少程序(类与类)之间的耦合度. *"KVO" ...

随机推荐

  1. 【C++ Primer | 15】C++类内存分布

    C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承.虚函数存在的情况下. 下面可以定义一个类,像下面这样: c ...

  2. 基于jsp+servlet图书管理系统之后台用户信息插入操作

    前奏: 刚开始接触博客园写博客,就是写写平时学的基础知识,慢慢发现大神写的博客思路很清晰,知识很丰富,非常又价值,反思自己写的,顿时感觉非常low,有相当长一段时间没有分享自己的知识.于是静下心来钻研 ...

  3. MySQL安装详细图解整理

    MySQL安装详细图解 2018-08-19  08:32:33 一.MYSQL的安装 1.打开下载的mysql安装文件mysql-5.0.27-win64.zip,双击解压缩,运行“setup.ex ...

  4. [CodeForces-1036E] Covered Points 暴力 GCD 求交点

    题意: 在二维平面上给出n条不共线的线段,问这些线段总共覆盖到了多少个整数点 解法: 用GCD可求得一条线段覆盖了多少整数点,然后暴力枚举线段,求交点,对于相应的 整数交点,结果-1即可 #inclu ...

  5. Python常用模块--base64

    作用:对一些保密性不强的信息进行加密,变为人类不能直接理解的字符串,但是可以反向解密,是一种‘防君子,不防小人’的措施. 例如:在一些项目中,接口的报文是通过base64加密传输的,所以在进行接口自动 ...

  6. iOS 技术篇: 如何利用dsym文件分析苹果被拒日志

    今天提审被拒了.伤心

  7. html 转成 pdf 进行预览、下载、打印

    html 页面转成 pdf,直接看代码: 参考地址: https://github.com/linwalker/render-html-to-pdf 给出代码 方便粘贴: var downPdf = ...

  8. [Agc005D]K Perm Counting

    [Agc005D] K Perm Counting Description 糟糕爷特别喜爱排列.他正在构造一个长度为N的排列.但是他特别讨厌正整数K.因此他认为一个排列很糟糕,当且仅当存在至少一个i( ...

  9. BZOJ.1009.[HNOI2008]GT考试(KMP DP 矩阵快速幂)

    题目链接 设f[i][j]为当前是第i位考号.现在匹配到第j位(已有j-1位和A[]匹配)的方案数 因为假如当前匹配j位,如果选择的下一位与A[j+1]不同,那么新的匹配位数是fail[j]而不是0, ...

  10. 学JAVA二十一天,自定义数组

    今天就说一下自定义数组,至于要怎么用,我也不知道,反正逼格挺高的. 闲话不多说,开始: 首先,自定义数组首先要创建一个类,用来做自定义数组的类型. public class User{ private ...