美文网首页
Association源码解读

Association源码解读

作者: helinyu | 来源:发表于2022-02-17 14:41 被阅读0次
    // 设置对象的关联方法
    void _object_set_associative_reference(id object, const void *key, id value, uintptr_t policy)
    {
        // This code used to work when nil was passed for object and key. Some code
        // probably relies on that to not crash. Check and handle it explicitly.
        // rdar://problem/44094390
        if (!object && !value) return; // 关联对象和值都不存在的时候
    
        if (object->getIsa()->forbidsAssociatedObjects()) // 判断是否禁止关联对象
            _objc_fatal("objc_setAssociatedObject called on instance (%p) of class %s which does not allow associated objects", object, object_getClassName(object));
    
    //     objc_object objc对象 , DisguisedPtr 伪装指针对象 , 它们都是什么? 这个需要来了解一下
        DisguisedPtr<objc_object> disguised{(objc_object *)object}; // 初始化一个伪装对象
        ObjcAssociation association{policy, value}; // 通过策略和值初始化对象
    
        // retain the new value (if any) outside the lock.
        association.acquireValue(); // 这里处理了什么? 增加引用计数器在锁的外面
    
        bool isFirstAssociation = false; // 是否第一次关联
        {
            AssociationsManager manager; // 管理对象
            AssociationsHashMap &associations(manager.get()); // hash映射
    
            if (value) { // 如果有值 , 处理
                auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});
                if (refs_result.second) {
                    /* it's the first association we make */
                    isFirstAssociation = true;
                }
    
                /* establish or replace the association */
                auto &refs = refs_result.first->second;
                auto result = refs.try_emplace(key, std::move(association));
                if (!result.second) {
                    association.swap(result.first->second);
                }
            } else { // 没有值的时候出来
                auto refs_it = associations.find(disguised);
                if (refs_it != associations.end()) {
                    auto &refs = refs_it->second;
                    auto it = refs.find(key);
                    if (it != refs.end()) {
                        association.swap(it->second);
                        refs.erase(it);
                        if (refs.size() == 0) {
                            associations.erase(refs_it);
                        }
                    }
                }
            }
        }
    
        // Call setHasAssociatedObjects outside the lock, since this
        // will call the object's _noteAssociatedObjects method if it
        // has one, and this may trigger +initialize which might do
        // arbitrary stuff, including setting more associated objects.
        if (isFirstAssociation)
            object->setHasAssociatedObjects(); // 如果是第一次关联, 这个就要设置关联对象
    
        // release the old value (outside of the lock).
        association.releaseHeldValue(); // 移除就的值
    }
    
    
    Assocation 初始化的流程

    PS: 里面的内容基本上入上面概括, 不过里面的使用的结构已经发生了变化了。 为什么使用新的数据结构。

    需要看一下里面的结构的具体实现过程。里面是如何进行实现的。

    旧版本的实现结构不同

    相关文章

      网友评论

          本文标题:Association源码解读

          本文链接:https://www.haomeiwen.com/subject/yohslrtx.html