类扩展&分类关联对象底层探究

2020-10-28  本文已影响0人  猿人

一、分类及扩展

分类又名 Category、类别
类扩展又名 Extension
类扩展探究

类扩展创建方式

类扩展底层原理探索

写一个类扩展并通过clang查看其源码

clang -rewrite-objc main.mm -o main.cpp
截屏2020-10-27 下午3.06.08.png
截屏2020-10-27 下午3.10.14.png 截屏2020-10-27 下午3.15.26.png

总结

分类关联对象底层探究

截屏2020-10-27 下午3.51.40.png
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));
/// 将object 伪装成 DisguisedPtr 类型数据结构
    DisguisedPtr<objc_object> disguised{(objc_object *)object};
/// 将策略 和 value 存入 ObjcAssociation 数据结构中
    ObjcAssociation association{policy, value};

    // retain the new value (if any) outside the lock.
    association.acquireValue();
/// 局部作用域
    {
///初始化一个关联 管理对象  在构造时加锁,析构时开锁
        AssociationsManager manager;
 
///   AssociationsHashMap 类型 就是一个嵌套的DenseMap 
///DenseMap<DisguisedPtr<objc_object>, DenseMap<const void *, ObjcAssociation>>
///   manager.get() :
/// 获取的是一个 static的_mapStorage变量 associations数据为manager.get()
///获取而来 所以associations是全局静态变量
        AssociationsHashMap &associations(manager.get());

        if (value) {
//    try_emplace:         在这disguised作为key查找,如果已经在associations表中,就把查
/// 找到的桶作为DenseMapIterator的位置指针进行初始化,然后用pair包装后返回;key
///没在associations表中就把disguised作为key,ObjectAssociationMap{}作为value存入
///桶中,然后把该桶作为DenseMapIterator的位置指针进行初始化,然后用pair包装后
///返回。返回值类型std::pair<DenseMapIterator, bool>
            auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});
            if (refs_result.second) {
                //能进来这里,说明disguised为key的桶是新插入进来的,所以根据条件设置isa_t中的has_assoc位为true
                object->setHasAssociatedObjects();
            }

            //找到associations中的disguised对应的ObjectAssociationMap表
            auto &refs = refs_result.first->second;
            //用key在ObjectAssociationMap表中查找,如果表中不存在该key那么就把key和association对应插入到ObjectAssociationMap中
            auto result = refs.try_emplace(key, std::move(association));
            //result.second为false, 说明ObjectAssociationMap表中原来已有该key,不会移动,所以这里进行了swap的操作来交换association的值。
            if (!result.second) {
                association.swap(result.first->second);
            }
        } else {   //value为nil, 取消关联。
        //先从associations表中找到disguised对应的ObjectAssociationMap表,用pair包装后返回。
            auto refs_it = associations.find(disguised);
            //如果从associations表中找到了disguised对应的ObjectAssociationMap表
            if (refs_it != associations.end()) {
                //从pair中拿到ObjectAssociationMap表
                auto &refs = refs_it->second;
                //从ObjectAssociationMap表中查找key对应的association,然后把它作为DenseMapIterator的位置指针初始化后返回
                auto it = refs.find(key);
                //如果找到了就进去
                if (it != refs.end()) {
                    //这里交换值是为了把要擦除的association记录下来,因为下面还要进行releaseHeldValue
                    association.swap(it->second);
                    //从ObjectAssociationMap表中擦除association以及其他相应的操作
                    refs.erase(it);
                    if (refs.size() == 0) {
                        //说明没有关联的值了,从associations表中擦除ObjectAssociationMap表
                        associations.erase(refs_it);
                    }
                }
            }
        }
    }

    // release the old value (outside of the lock).//释放
    association.releaseHeldValue();
}
 
// class AssociationsManager manages a lock / hash table singleton pair.
// Allocating an instance acquires the lock

class AssociationsManager {
    using Storage = ExplicitInitDenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap>;
    static Storage _mapStorage;

public:
    AssociationsManager()   { AssociationsManagerLock.lock(); }///初始化 加锁
    ~AssociationsManager()  { AssociationsManagerLock.unlock(); }///析构 解锁

    AssociationsHashMap &get() { 
        return _mapStorage.get();
    }

    static void init() {
        _mapStorage.init();
    }
}

从中可以看出get() 方法获取的为全局静态变量 唯一的

class ObjcAssociation {
    uintptr_t _policy;
    id _value;
.....省略
}

typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;
typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;
  
截屏2020-10-27 下午10.25.39.png 2251862-56319ac00d5108f6.jpg 截屏2020-10-27 下午10.59.33.png

优化打印值

///1.KeyT
//pair<objc::DenseMapIterator<DisguisedPtr<objc_object>,

///2.ValueT
//objc::DenseMap<const void *, objc::ObjcAssociation, objc::DenseMapValueInfo<objc::ObjcAssociation>, objc::DenseMapInfo<const void *>,    objc::detail::DenseMapPair<const void *, objc::ObjcAssociation> >,

///3.DenseMapValueInfo<ValueT>    ->      ValueInfoT
//objc::DenseMapValueInfo<objc::DenseMap<const void *, objc::ObjcAssociation, objc::DenseMapValueInfo<objc::ObjcAssociation>, objc::DenseMapInfo<const void *>, objc::detail::DenseMapPair<const void *, objc::ObjcAssociation> > >,

///4.DenseMapInfo<KeyT>      ->     KeyInfoT
//objc::DenseMapInfo<DisguisedPtr<objc_object> >,

///5.detail::DenseMapPair<KeyT, ValueT>  ->      BucketT
//objc::detail::DenseMapPair<DisguisedPtr<objc_object>, objc::DenseMap<const void *, objc::ObjcAssociation, objc::DenseMapValueInfo<objc::ObjcAssociation>, objc::DenseMapInfo<const void *>, objc::detail::DenseMapPair<const void *, objc::ObjcAssociation> > >,

///6.false
//false>,

///7.bool
//bool>

到这里可以得出下面的一张关系图


关联对象结构 2.jpg

objc_getAssociatedObject源码分析

id objc_getAssociatedObject(id object, const void *key)
{
    return _object_get_associative_reference(object, key);
}

id _object_get_associative_reference(id object, const void *key)
{   
    //先初始化一个用来接收值的association
    ObjcAssociation association{};
    {
        AssociationsManager manager;
        AssociationsHashMap &associations(manager.get());
        //用object作为key从associations表中找到对应的ObjectAssociationMap表
        AssociationsHashMap::iterator i = associations.find((objc_object *)object);
        if (i != associations.end()) {
            ObjectAssociationMap &refs = i->second;
            //用key在ObjectAssociationMap表中搜索对应的ObjcAssociation
            ObjectAssociationMap::iterator j = refs.find(key);
            if (j != refs.end()) {
                //找到后赋值给association,然后retain
                association = j->second;
                association.retainReturnedValue();
            }
        }
    }

    return association.autoreleaseReturnedValue();
}

关联对象释放
通过_objc_rootDealloc->rootDealloc->object_dispose->objc_destructInstance

void *objc_destructInstance(id obj) 
{
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj->hasCxxDtor();
        bool assoc = obj->hasAssociatedObjects();

        // This order is important.
        if (cxx) object_cxxDestruct(obj);
        //如果有关联对象,移除
        if (assoc) _object_remove_assocations(obj);
        obj->clearDeallocating();
    }
    return obj;
}

void _object_remove_assocations(id object)
{
    ObjectAssociationMap refs{};
    {
        AssociationsManager manager;
        AssociationsHashMap &associations(manager.get());
        AssociationsHashMap::iterator i = associations.find((objc_object *)object);
        if (i != associations.end()) {
            refs.swap(i->second);
            associations.erase(i);
        }
    }
    // release everything (outside of the lock).
    for (auto &i: refs) {
        i.second.releaseHeldValue();
    }
}

从中可以看出关联对象不用手动移除,在对象释放时会自动移除。

总结

上一篇下一篇

猜你喜欢

热点阅读