用RunTime给Category添加weak属性

2019-05-11  本文已影响0人  _moses

我们知道用RunTime给Category添加属性的时候,系统只提供了下面五个枚举

OBJC_ASSOCIATION_ASSIGN = 0, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, 
OBJC_ASSOCIATION_RETAIN = 01401,  
OBJC_ASSOCIATION_COPY = 01403,    

我们还知道assign和weak的区别就在于引用计数为0的时候weak会自动置空,而assign不会。
那我们是不是可以将assign改造成weak呢?

思路大概是这样的:新建一个中间类,然后让这个assign属性强引用(retain)这个中间类的对象,然后再让这个中间对象弱引用(weak)self,然后在中间对象销毁的时候将assign对象置空即可。

废话少说,直接上代码

@interface UIView (MSCategory)

@property (nonatomic, weak) UIView *test;

@end

@implementation UIView (MSCategory)

- (void)setTest:(UIView *)test {
    SEL sel = @selector(test);
    objc_setAssociatedObject(self, sel, test, OBJC_ASSOCIATION_ASSIGN); // self持有test
    if (test) {
        // MSRuntimeWeakPropertyMiddleModel就是那个中间类
        MSRuntimeWeakPropertyMiddleModel *model = [MSRuntimeWeakPropertyMiddleModel new];
        model.obj = self; // model持有self
        model.property = NSStringFromSelector(sel);
        objc_setAssociatedObject(test, sel, model, OBJC_ASSOCIATION_RETAIN_NONATOMIC); // test持有model
    }
}

- (UIView *)test {
    return objc_getAssociatedObject(self, @selector(test));
}

@end
@interface MSRuntimeWeakPropertyMiddleModel : NSObject

@property (nonatomic, weak) id obj; /**< 宿主对象 */
@property (nonatomic, copy) NSString *property; /**< 属性名 */

@end

@ implementation MSRuntimeWeakPropertyMiddleModel

- (void)dealloc {
    [self.obj setValue:nil forKey:self.property];
}

@end
上一篇下一篇

猜你喜欢

热点阅读