需求: 實現分類中新增弱引用屬性
@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
複製程式碼