给分类添加delegate属性
分类可以方便的对现有类进行扩展, 一般是新增方法, 但是有时候难以避免的, 我们可能需要为分类添加属性, 通常我们使用关联对象实现此功能.
然而,当我们希望添加weak类型的属性时, 会遇到一点点困难, 比如为分类添加delegate属性.
我们希望delegate对象存在时, 正常使用此属性对象,而当delegate对象释放时, 此delegate属性可以像真正的weak属性那样自动置为nil.然后关联对象本身并不能实现这一点.
如果我们使用assign类型的关联对象添加此属性, 还肯能导致程序发生crash.因为当delegate释放时, delegate所记录的值还存在, 此时访问他就会发生crash,因为访问了已经释放的对象地址.
那么我们应该如何解决这个问题呢?
嵌套weak属性
解决办法是:给分类添加strong属性的关联对象, 这个关联对象持有一个真正的weak属性, 然后把delegate对象赋值给这个weak属性.
嵌套了weak属性的container类:
@interface HWLAssociatedObjContainer : NSObject
@property (nonatomic, weak) id <NSObject> weakObj;
@end
@implementation HWLAssociatedObjContainer
@end
使用container实现weak属性的分类
@interface HWLCategoryClass (weakProperty)
@property (nonatomic, weak) id<someProtocol> obj_delegate;
@end
@interface HWLCategoryClass ()
@property (nonatomic, strong) HWLAssociatedObjContainer *obj_delegateContainer;
@end
@implementation HWLCategoryClass (weakProperty)
- (id< HWLAssociatedObjContainer >) obj_delegate {
return (id<someProtocol>)self.nav_delegateContainer.weakObj;
}
- (void)setObj_delegate:(id<someProtocol>) obj_delegate {
if (self.obj_delegateContainer) {
self.obj_delegateContainer.weakObj = obj_delegate;
} else {
HWLAssociatedObjContainer *tAssociatedObjContainer = [[HWLAssociatedObjContainer alloc] init];
tAssociatedObjContainer.weakObj = obj_delegate;
self.obj_delegateContainer = tAssociatedObjContainer;
}
}
- (HWLAssociatedObjContainer*)obj_delegateContainer {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setObj_delegateContainer:(HWLAssociatedObjContainer *)obj_delegateContainer {
objc_setAssociatedObject(self, @selector(obj_delegateContainer), obj_delegateContainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
如上代码所示,
给分类添加strong关联对象属性,此strong关联对象持有一个weak属性,
当给delegate赋时, 检查strong关联对象是否存在, 不存在则创建.然后给此strong关联对象的weak属性赋值delegate对象.
这样当delegate对象释放时, strong关联对象持有的weak属性会自动置nil.