美文网首页
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