iOS - 关联对象的实现

根据源码总结一下关联对象(Associated Objects)的实现:

1. 关联对象的基本结构

objectivec 复制代码
// 对象的 isa 结构中包含关联对象标记
union isa_t {
    struct {
        uintptr_t nonpointer     : 1;  // 是否使用优化的 isa
        uintptr_t has_assoc      : 1;  // 是否有关联对象
        // ...其他位域
    };
};

// 关联对象表
struct AssociationsManager {
    static AssociationsHashMap *_map;  // 全局的关联对象哈希表
};

2. 关联对象的存储

objectivec 复制代码
// 关联对象的存储结构
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. 关联对象的操作

objectivec 复制代码
// 设置关联对象
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. 内存管理

objectivec 复制代码
// 对象释放时清理关联对象
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. 线程安全

objectivec 复制代码
class AssociationsManager {
    static OSSpinLock _lock;  // 自旋锁保护

    void set(id object, const void *key, id value, 
             objc_AssociationPolicy policy) {
        OSSpinLockLock(&_lock);
        // 设置关联对象
        OSSpinLockUnlock(&_lock);
    }
};

6. 性能优化

objectivec 复制代码
// 1. 使用自旋锁而不是互斥锁
static OSSpinLock AssociationsManagerLock;

// 2. 哈希表实现
typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;
typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;

7. 关键特性

  1. 动态性:
objectivec 复制代码
// 运行时动态添加属性
objc_setAssociatedObject(self, &key, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  1. 内存管理:
objectivec 复制代码
// 不同的关联策略
OBJC_ASSOCIATION_ASSIGN           // 弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC // 强引用,非原子
OBJC_ASSOCIATION_COPY_NONATOMIC   // 复制,非原子
  1. 线程安全:
objectivec 复制代码
// 通过自旋锁保证线程安全
OSSpinLockLock(&_lock);
// 操作关联对象
OSSpinLockUnlock(&_lock);

关联对象的实现特点:

  1. 使用全局哈希表存储
  2. 支持不同的内存管理策略
  3. 保证线程安全
  4. 对象释放时自动清理
  5. 通过 isa 标记优化查找
相关推荐
FPGA小迷弟1 小时前
FPGA 与千兆以太网:各类物理接口的形式、区别、使用方法与应用场景详解
tcp/ip·macos·fpga开发·udp·fpga
茶底世界之下4 小时前
斜光下的旧自行车:用 Awaking 留一版复古胶片色
ios·app·产品
2501_916008897 小时前
iPhone 设备信息查看,用 KeyMob 看型号、序列号、电池健康和 UDID
android·ios·小程序·https·uni-app·iphone·webview
茶底世界之下1 天前
iPhone Duo 适配实战,Awaking 踩过的 8 个坑
ios·swiftui·swift
跨境数据猎手1 天前
HTTP 响应体编码与压缩:识别、解码
网络协议·http·ios
也非非也1 天前
iPhone 中国区 AI 落地:Apple 与阿里千问合作的技术观察
大数据·人工智能·ios·agent·iphone·智子
茶底世界之下1 天前
同一片泳池,清透还是奶油胶片?用 Awaking 做两版成片
ios
2501_916008891 天前
iOS App 图标、启动屏和多语言搭配 方法,上架前使用KXBuild一次做好 App 图标
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_915918411 天前
iOS 推送通知怎么实现,从 APNs p8 密钥到 iOS 真机收到第一条推送
vscode·ios·objective-c·个人开发·swift·敏捷流程
周小董2 天前
[1379]mac安装nvm
macos