iOS开发之 runtime(32) :future named class介绍

本系列博客是本人的源码阅读笔记,如果有 iOS 开发者在看 runtime 的,欢迎大家多多交流。为了方便讨论,本人新建了一个微信群(iOS技术讨论群),想要加入的,请添加本人微信:zhujinhui207407,【加我前请备注:ios 】,本人博客http://www.kyson.cn 也在不停的更新中,欢迎一起讨论

本文完整版详见笔者小专栏:https://xiaozhuanlan.com/runtime

前言

在前面的文章中我们分析过,存储在 hash map 中数据的几个类:

  • gdb_objc_realized_classes:已经实现过的类列表
  • remapped_class_map,已经重映射的类列表

今天我们就讲另外一个和上面两个息息相关的 hash map :future_named_class_map,它存储了 ”未来“要实现的类?这里先卖个关子,等笔者先将其分析一下再说:

创建

static NXMapTable *future_named_class_map = nil;
static NXMapTable *futureNamedClasses()
{
    runtimeLock.assertWriting();
    if (future_named_class_map) return future_named_class_map;
    // future_named_class_map is big enough for CF's classes and a few others
    future_named_class_map =  NXCreateMapTable(NXStrValueMapPrototype, 32);
    return future_named_class_map;
}

以上代码清晰明了:如果有的话使用,没有的话则创建。

获取

OBJC_EXPORT Class objc_getFutureClass(const char *name) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0)
    OBJC_ARC_UNAVAILABLE;

这个方法需要注意,它是在 runtime.h 中声明的,也就是说,他其实是对外暴露的,可以直接使用,不过看其注释:

/*** Used by CoreFoundation's toll-free bridging.
Return the id of the named class.
@return The id of the named class, or an uninitialized class
structure that will be used for the class when and if it does
get loaded.
@warning Do not call this function yourself.
***/

注意最后一句: 不要主动调用这个函数!

我们来看一下这个函数的实现:

Class objc_getFutureClass(const char *name)
{
    Class cls;
    cls = look_up_class(name, YES, NO);
    if (cls) {
        if (PrintFuture) {
            _objc_inform("FUTURE: found %p already in use for %s", 
                         (void*)cls, name);
        }
        return cls;
    }
    return _objc_allocateFutureClass(name);
}

其中函数 look_up_class 这里先不多做介绍了,里面逻辑较多,而且不是这个函数的重点,重点是最后一句:_objc_allocateFutureClass(name) 它才是从 hash map 中获取对应值的函数,其实现如下 :

Class _objc_allocateFutureClass(const char *name)
{
    rwlock_writer_t lock(runtimeLock);
    Class cls;
    NXMapTable *map = futureNamedClasses();
    if ((cls = (Class)NXMapGet(map, name))) {
        // Already have a future class for this name.
        return cls;
    }
    cls = _calloc_class(sizeof(objc_class));
    addFutureNamedClass(name, cls);
    return cls;
}

很容易理解:有的话就通过方法 NXMapGet 取出来,没有的话则创建。

移除

static Class popFutureNamedClass(const char *name)
{
    runtimeLock.assertWriting();

    Class cls = nil;

    if (future_named_class_map) {
        cls = (Class)NXMapKeyFreeingRemove(future_named_class_map, name);
        if (cls && NXCountMapTable(future_named_class_map) == 0) {
            NXFreeMapTable(future_named_class_map);
            future_named_class_map = nil;
        }
    }

    return cls;
}

这个方法有点熟悉了,正是上文介绍的 remap 的条件之一。上一篇文章讲述的是第一个条件,本文讲的是第二个条件。这两个条件无论哪一个符合都会调用方法:addRemappedClass,即向 remapped_class_map 中插入数据。这里画一幅图加深理解:



以上这张图已经说明了之前笔者分析的两个 map 与本文的 map 之间的关系。

总结

future named class 的介绍就到这里了,希望大家有所收获。其实笔者看来,不管是上一篇文章的 remapped_class_map 还是本文的 future_named_class_map 里面的数据都是空。remapped_class_map 有数据是需要一定条件,而 future_named_class_map 有数据也是需要先 add 的,所以大家对于这两个 map 只需要有个大概的概念就好,后面如果真的碰到他们有数据,我们在详细分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章