需求: 實現(xiàn)分類中添加弱引用屬性
@interface ViewController (WeakDelegate)
@property (nonatomic, weak) id delegate;
@end
眾所周知runtime中關(guān)聯(lián)屬性的幾種類型如下:
/**
* 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. */
};
但如果想實現(xiàn)弱引用的關(guān)聯(lián)對象就無法使用上面任意一條枚舉。
這里通過使用block打包/解包的方式完成需求关串。
首先邢滑,定義打包和解包函數(shù):
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;
}
然后拴曲,在常規(guī)的形式下添加打包和解包即可:
@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
打印結(jié)果:
testCategoryWeakDelegate[65095:1585708] 0x600000208690
testCategoryWeakDelegate[65095:1585708] 1 == 1
testCategoryWeakDelegate[65095:1585708] 2 == 2
testCategoryWeakDelegate[65095:1585708] 3 == 2
testCategoryWeakDelegate[65095:1585708] 0x600000208690