我们可以自己创建一个 A 类,然后在“宿主对象”和“值对象”建立
weak
关系的时候,偷偷地创建一个 A 类的实例 a,绑定在 “值对象” 上。当“值对象”销毁后,这个 a 也会被销毁。而 A 类是*的内部类,其
dealloc
方法可以随意改造。这样就可以把
宿主对象.某属性 = nil
这段代码写在 A 类的 dealloc
方法里。由于
[a dealloc]
与 [值对象 dealloc]
是一起执行的,我们便做到在不改原有类的情况下捕获原有类的 dealloc
方法。总结来说在
Category
里我们要用关联对象的方法让“值类型”强引用 a。/** 宿主类的分类实现 */
@implementation MUHostClass (Association)
const static char kValueObject = '0';
- (void)setValueObject:(MUValueClass *)valueObject {
objc_setAssociatedObject(self, &kValueObject, valueObject, OBJC_ASSOCIATION_ASSIGN);
/** * 1. 虽然这里没有循环引用,但是还是需要把弱引用丢给 block *
因为 valueObj 持有 weakTask,weakTask 持有 block,block 持有 self *
因此 self 至少要等到 valueObj 销毁后才能销毁。严重影响到 self 的生命周期 **/
__weak typeof(self) wself = self;
[valueObject setWeakReferenceTask:^{
objc_setAssociatedObject(wself, &kValueObject, nil, OBJC_ASSOCIATION_ASSIGN); }
];
}
- (MUValueClass *)valueObject {
return objc_getAssociatedObject(self, &kValueObject);
}
@end
/** 给所有的类添加扩展 */
@implementation NSObject (MUWeakTask)
static const char kWeakTask = '0';
- (void)setWeakReferenceTask:(TaskBlock)task {
MUWeakTask *weakTask = [MUWeakTask taskWithTaskBlock:task];
objc_setAssociatedObject(self, &kWeakTask, weakTask, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
/** 传说中的 A 类 */
@implementation MUWeakTask
- (instancetype)initWithTaskBlock:(TaskBlock)taskBlock{
self = [super init];
if (self) {
_taskBlock = [taskBlock copy];
}
return self;
}
+ (instancetype)taskWithTaskBlock:(TaskBlock)taskBlock {
return [[self alloc] initWithTaskBlock:taskBlock];
}
- (void)dealloc {
if (self.taskBlock) {
self.taskBlock();
}
}
@end