Associated Objects

Associated Objects

通过以下三个函数可以进行关联对象的相关操作:

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, const void *key);
void objc_removeAssociatedObjects(id object);

key 应该是常量的,唯一的,在 settergetter 方法中可以进行访问:

static char kAssociatedObjectKey;

objc_getAssociatedObject(self, &kAssociatedObjectKey);

但是由于 selector 是唯一的,所以可以直接使用 selector

https://twitter.com/bbum/status/3609098005

不要调用 objc_removeAssociatedObjects 来移除关联对象,因为会移除所有关联对象。正确的做法是调用 objc_setAssociatedObject 方法并传入 nil 来清除关联。

比起其他解决问题的方法,关联对象应该被视为最后的选择(事实上关联对象也不应该作为首选方法)。

AssociatedObject 解析

关联对象 AssociatedObject 完全解析 - 面向信仰编程

  • 关联对象其实就是 ObjcAssociation 对象
  • 关联对象由 AssociationsManager 管理并在 AssociationsHashMap 存储
  • 对象的指针以及其对应 ObjectAssociationMap 以键值对的形式存储在 AssociationsHashMap 中
  • ObjectAssociationMap 则是用于存储关联对象的数据结构
  • 每一个对象都有一个标记位 has_assoc 指示对象是否含有关联对象

iOS 中的关联对象

iOS 中的关联对象

Weak Associated Object

Weak Associated Object | 张不坏的博客

起一个中间层,叫 container 或者 wrapper 都可以:

@interface WeakAssociatedObjectWrapper : NSObject

@property (nonatomic, weak) id object;

@end

@implementation WeakAssociatedObjectWrapper

@end

@interface UIView (ViewController)

@property (nonatomic, weak) UIViewController *vc;

@end

@implementation UIView (ViewController)

- (void)setVc:(UIViewController *)vc {
    WeakAssociatedObjectWrapper *wrapper = [WeakAssociatedObjectWrapper new];
    wrapper.object = vc;
    objc_setAssociatedObject(self, @selector(vc), wrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIViewController *)vc {
    WeakAssociatedObjectWrapper *wrapper = objc_getAssociatedObject(self, _cmd);
    return wrapper.object;
}

@end

应用

ChenYilong/CYLDeallocBlockExecutor

通过 Associated Objects 在对象 dealloc 会释放的原理,可以给对象添加一个属性,然后在这个属性 dealloc 时进行相关操作,可以达到对象 dealloc 进行对应操作的目的。