为对象添加一个释放时触发的block

有时我们需要在一个对象生命周期结束的时候触发一个操作,希望当该对象dealloc的时候调用一个外部指定的block,但又不希望直接hook dealloc方法,这样侵入性太强了.下面贴一段非常简单的实现方式,通过一个category给外部暴露一个block注入的接口,内部将该block封装到一个寄生对象中(Parasite),该寄生对象在dealoc的时候触发block调用,所有的寄生对象通过runtime的AssociatedObject机制与宿主共存亡,从而达到监控宿主生命周期的目的.

注意事项

  • block触发的线程与对象释放时的线程一致,请注意后续操作的线程安全.
  • 不要在block中强引用对象,否则引用循环释放不了;
  • 不要在block中通过weak引用对象,因为此时会返回nil;
    (根据WWDC2011,Session322对对象释放时间的描述,associated objects清除在对象生命周期中很晚才执行,通过被NSObject -dealloc方法调用的object_dispose()函数完成);

NSObject+Guard.h

12345678910
#import <Foundation/Foundation.h>

@interface NSObject (Guard)

/** @brief 添加一个block,当该对象释放时被调用 **/- (void)guard_addDeallocBlock:(void(^)(void))block;

@end

NSObject+Guard.m

12345678910111213141516171819202122232425262728293031323334
#import "NSObject+Guard.h"#import <objc/runtime.h>

@interface Parasite : NSObject@property (nonatomic, copy) void(^deallocBlock)(void);@end

@implementation Parasite

- (void)dealloc {    if (self.deallocBlock) {        self.deallocBlock();    }}

@end

@implementation NSObject (Guard)

- (void)guard_addDeallocBlock:(void(^)(void))block {    @synchronized (self) {        static NSString *kAssociatedKey = nil;        NSMutableArray *parasiteList = objc_getAssociatedObject(self, &kAssociatedKey);        if (!parasiteList) {            parasiteList = [NSMutableArray new];            objc_setAssociatedObject(self, &kAssociatedKey, parasiteList, OBJC_ASSOCIATION_RETAIN_NONATOMIC);        }        Parasite *parasite = [Parasite new];        parasite.deallocBlock = block;        [parasiteList addObject: parasite];    }}

@end
时间: 2024-10-10 04:08:27

为对象添加一个释放时触发的block的相关文章

为对象添加一个新的方法

例定义一个方法,为Date对象添加一个新的成员方法,转换为形如 y-m-d<br>h:m:s Date.prototype.stringify = function(){ var s= this.getFullYear()+'-'; s+= (this.getMonth()+1)+'-'; s+= this.getDate()+' '; s+= this.getHours()+':'; s+= this.getMinutes()+':'; s+= this.getSeconds(); retu

为Array对象添加一个去重的方法(ES5和ES6的实现)

输入一个例子 [false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN].uniq() 需要输出 [false, true, undefined, null, NaN, 0, 1, {}, {}, 'a'] 分析 题目要求给Array添加方法,所以我们需要用到prototype,数组去重本身算法不是很难,但是在Javascript中很多人会忽视NaN的存在,因为JS中NaN != NaN 在不考虑NaN的情况下我是使用inde

[python] pexpect.spawn的对象child调用read()时触发TIMEOUT异常

设计意图:初始化一次spawn对象,执行ssh后下发,一系列cmds.网上大部分时通过ssh [email protected] cmd的方法,这样的话,我就之需要通过for调用: def SSH_COMMANDS(ip,user,passwd,command):     try:         ssh_pc = pexpect.spawn('ssh %[email protected]%s %s' % (user,ip,command),timeout=5,logfile=logfile)

JArray数组每个JObject对象添加一个键值对

JArray ja = new JArray(); JObject jo = new JObject(); jo.Add("1","1"); ja.Add(jo); ja.Add(jo); ja.ToList().ForEach(x => ((JObject)x).Add("2", "2")); Console.WriteLine(ja.ToString());

javascript鼠标双击时触发事件大全

javascript事件列表解说 事件 浏览器支持 解说 一般事件 onclick IE3.N2 鼠标点击时触发此事件 ondblclick IE4.N4 鼠标双击时触发此事件 onmousedown IE4.N4 按下鼠标时触发此事件 onmouseup IE4.N4 鼠标按下后松开鼠标时触发此事件 onmouseover IE3.N2 当鼠标移动到某对象范围的上方时触发此事件 onmousemove IE4.N4 鼠标移动时触发此事件 onmouseout IE4.N3 当鼠标离开某对象范围

你会如何给全局对象添加toString()方法

首先,在讨论如何给所有方法window对象添加tostring方法的时候,我们先来说说window的对象继承与对象实例,以及构造函数的this指针,还有变量的提升与方法的调用方式,最终一探window对象与Window方法(函数)的处理方式. 在说window对象之前,请让我们一起写一个实例的方法暖暖身,跳水之前应该做热身动作,虽然我们不跳水,不过写代码也需要做一个热身,这样才能适应下面的高难度动作. 废话好多,裁判看不下去了,开始准备你的姿势,让我们开场就拿个满分,吓死裁判,但是看到裁判吓到自

SAS HASH :内存失败时,Hash对象添加了***个项

处理千万观测数据的小伙伴,辛苦等了一两个小时,结果发现以下报错,心如死灰: ERROR: 内存失败时,Hash 对象添加了 4587504 个项. FATAL: 内存不足,无法执行 DATA 步程序. 在"EXECUTION"阶段中止.ERROR: 由于内存不足,SAS 系统停止了对该步的处理.NOTE: 从数据集 WORK.T_QUERY. 读取了 82425420 个观测WARNING: 数据集 D.T_QUERY 可能不完整.该步停止时,共有 4587503 个观测和 97 个变

移动用户至OU报错 “无法移动对象,试图给目录添加一个名称已在使用的对象”

因部门架构调整,需要将所有用户占时放置至一个OU内,但是移动时候经常会报错"无法移动对象,试图给目录添加一个名称已在使用的对象"如下图 解决方式如下,打开AD管理中心,打开兰中属性,将全名修改为兰中1 保存后可以看到用户的名称已由原来的兰中变为兰中1 这时候就可以成功移动了. 使用命令更改如下图所示 更改此名称并不会影响到用户登录邮箱所显示的账户名,以及系统内显示的账户名

EasyUi datagrid(onClickCell:用户单击一个单元格时触发 ) 單擊編輯 editor:{type: &#39;combobox&#39;}

1.columns列[一個單元格] 添加combobox下拉選項 $("#userGrid").datagrid({ singleSelect: true,            onClickCell: function (index, field, value) {                //Field = field;                //                var rows = $('#' + UserGrid).datagrid('getRo