美文网首页iOS开发之深入理解runtimeiOS精选
iOS开发之 runtime(32) :future named

iOS开发之 runtime(32) :future named

作者: kyson老师 | 来源:发表于2019-06-26 00:27 被阅读5次
    logo

    本系列博客是本人的源码阅读笔记,如果有 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 中插入数据。这里画一幅图加深理解:


    maps 之间关系

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

    总结

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

    相关文章

      网友评论

        本文标题:iOS开发之 runtime(32) :future named

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