为对象添加一个释放时触发的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

1
2
3
4
5
6
7
8
9
10
#import <Foundation/Foundation.h>

@interface NSObject (Guard)

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

@end

NSObject+Guard.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#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

转载于:https://www.cnblogs.com/xiao-love-meng/p/5757560.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值