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 只需要有個大概的概念就好,後面如果真的碰到他們有數據,我們在詳細分析。

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