如何实现分类中添加弱引用属性

需求: 实现分类中添加弱引用属性

@interface ViewController (WeakDelegate)

@property (nonatomic, weak) id delegate;

@end

众所周知runtime中关联属性的几种类型如下:

/**
 * Policies related to associative references.
 * These are options to objc_setAssociatedObject()
 */
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
                                            *   The association is made atomically. */
    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
                                            *   The association is made atomically. */
};

但如果想实现弱引用的关联对象就无法使用上面任意一条枚举。
这里通过使用block打包/解包的方式完成需求。

首先,定义打包和解包函数:

typedef id weakid;
typedef weakid(^WeakReference)(void);

WeakReference packWeakReference(id ref) {
    __weak weakid weakRef = ref;
    return ^{
        return weakRef;
    };
}

weakid unpackWeakReference(WeakReference closure) {
    return closure ? closure() : nil;
}

然后,在常规的形式下添加打包和解包即可:

@implementation ViewController (WeakDelegate)

- (void)setDelegate:(id)delegate
{
    objc_setAssociatedObject(self, @selector(delegate), packWeakReference(delegate), OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (id)delegate
{
    return unpackWeakReference(objc_getAssociatedObject(self, @selector(delegate)));
}

@end

以下为测试代码

@interface ViewController ()

@property (nonatomic, strong) id ref;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSObject *test = [NSObject new];
    NSLog(@"%p",test);
    NSLog(@"1 == %@", [test valueForKey:@"retainCount"]);
    
    _ref = test;
    NSLog(@"2 == %@", [test valueForKey:@"retainCount"]);
    
    self.delegate = test;
    NSLog(@"3 == %@", [test valueForKey:@"retainCount"]);
    
    NSLog(@"%p",self.delegate);
}

@end

打印结果:

testCategoryWeakDelegate[65095:1585708] 0x600000208690
testCategoryWeakDelegate[65095:1585708] 1 == 1
testCategoryWeakDelegate[65095:1585708] 2 == 2
testCategoryWeakDelegate[65095:1585708] 3 == 2
testCategoryWeakDelegate[65095:1585708] 0x600000208690

完。

你可能感兴趣的:(如何实现分类中添加弱引用属性)