iOS - 关联对象的实现
根据源码总结一下关联对象(Associated Objects)的实现:
1. 关联对象的基本结构
// 对象的 isa 结构中包含关联对象标记
union isa_t {
struct {
uintptr_t nonpointer : 1; // 是否使用优化的 isa
uintptr_t has_assoc : 1; // 是否有关联对象
// ...其他位域
};
};
// 关联对象表
struct AssociationsManager {
static AssociationsHashMap *_map; // 全局的关联对象哈希表
};
2. 关联对象的存储
// 关联对象的存储结构
class ObjcAssociation {
uintptr_t _policy; // 关联策略
id _value; // 关联的值
// 关联策略
OBJC_ASSOCIATION_ASSIGN
OBJC_ASSOCIATION_RETAIN_NONATOMIC
OBJC_ASSOCIATION_COPY_NONATOMIC
OBJC_ASSOCIATION_RETAIN
OBJC_ASSOCIATION_COPY
};
3. 关联对象的操作
// 设置关联对象
void objc_setAssociatedObject(id object, const void *key, id value,
objc_AssociationPolicy policy) {
// 1. 标记对象有关联对象
object->isa.has_assoc = true;
// 2. 存储关联对象
AssociationsManager manager;
manager.set(object, key, value, policy);
}
// 获取关联对象
id objc_getAssociatedObject(id object, const void *key) {
// 从关联对象表中获取值
AssociationsManager manager;
return manager.get(object, key);
}
4. 内存管理
// 对象释放时清理关联对象
void _object_remove_assocations(id object) {
// 1. 获取对象的所有关联对象
AssociationsManager manager;
AssociationsHashMap &associations = manager.associations();
// 2. 根据策略释放关联对象
if ((entry = associations.find(object)) != associations.end()) {
// 清理关联对象
entry->second.clear();
// 从哈希表中移除
associations.erase(entry);
}
}
5. 线程安全
class AssociationsManager {
static OSSpinLock _lock; // 自旋锁保护
void set(id object, const void *key, id value,
objc_AssociationPolicy policy) {
OSSpinLockLock(&_lock);
// 设置关联对象
OSSpinLockUnlock(&_lock);
}
};
6. 性能优化
// 1. 使用自旋锁而不是互斥锁
static OSSpinLock AssociationsManagerLock;
// 2. 哈希表实现
typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;
typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;
7. 关键特性
1. 动态性:
// 运行时动态添加属性
objc_setAssociatedObject(self, &key, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2. 内存管理:
// 不同的关联策略
OBJC_ASSOCIATION_ASSIGN // 弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC // 强引用,非原子
OBJC_ASSOCIATION_COPY_NONATOMIC // 复制,非原子
3. 线程安全:
// 通过自旋锁保证线程安全
OSSpinLockLock(&_lock);
// 操作关联对象
OSSpinLockUnlock(&_lock);
关联对象的实现特点:
- 使用全局哈希表存储
- 支持不同的内存管理策略
- 保证线程安全
- 对象释放时自动清理
- 通过 isa 标记优化查找