本系列博客是本人的源碼閱讀筆記,如果有 iOS 開發(fā)者在看 runtime 的玉掸,歡迎大家多多交流伴挚。
前言
在前面的文章中我們分析過(guò),存儲(chǔ)在 hash map 中數(shù)據(jù)的幾個(gè)類:
- gdb_objc_realized_classes:已經(jīng)實(shí)現(xiàn)過(guò)的類列表
- remapped_class_map沦辙,已經(jīng)重映射的類列表
今天我們就講另外一個(gè)和上面兩個(gè)息息相關(guān)的 hash map :future_named_class_map夫植,它存儲(chǔ)了 ”未來(lái)“要實(shí)現(xiàn)的類?這里先賣個(gè)關(guān)子,等筆者先將其分析一下再說(shuō):
創(chuàng)建
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;
}
以上代碼清晰明了:如果有的話使用详民,沒(méi)有的話則創(chuàng)建延欠。
獲取
OBJC_EXPORT Class objc_getFutureClass(const char *name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0)
OBJC_ARC_UNAVAILABLE;
這個(gè)方法需要注意,它是在 runtime.h 中聲明的沈跨,也就是說(shuō)由捎,他其實(shí)是對(duì)外暴露的,可以直接使用饿凛,不過(guò)看其注釋:
/*** 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.
***/
注意最后一句: 不要主動(dòng)調(diào)用這個(gè)函數(shù)狞玛!
我們來(lái)看一下這個(gè)函數(shù)的實(shí)現(xiàn):
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);
}
其中函數(shù) look_up_class 這里先不多做介紹了,里面邏輯較多涧窒,而且不是這個(gè)函數(shù)的重點(diǎn)心肪,重點(diǎn)是最后一句:_objc_allocateFutureClass(name)
它才是從 hash map 中獲取對(duì)應(yīng)值的函數(shù),其實(shí)現(xiàn)如下 :
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;
}
很容易理解:有的話就通過(guò)方法 NXMapGet 取出來(lái)纠吴,沒(méi)有的話則創(chuàng)建硬鞍。
移除
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;
}
這個(gè)方法有點(diǎn)熟悉了,正是上文介紹的 remap 的條件之一戴已。上一篇文章講述的是第一個(gè)條件固该,本文講的是第二個(gè)條件。這兩個(gè)條件無(wú)論哪一個(gè)符合都會(huì)調(diào)用方法:addRemappedClass糖儡,即向 remapped_class_map 中插入數(shù)據(jù)蹬音。這里畫一幅圖加深理解:
以上這張圖已經(jīng)說(shuō)明了之前筆者分析的兩個(gè) map 與本文的 map 之間的關(guān)系。
總結(jié)
future named class 的介紹就到這里了休玩,希望大家有所收獲著淆。其實(shí)筆者看來(lái),不管是上一篇文章的 remapped_class_map 還是本文的 future_named_class_map 里面的數(shù)據(jù)都是空拴疤。remapped_class_map 有數(shù)據(jù)是需要一定條件永部,而 future_named_class_map 有數(shù)據(jù)也是需要先 add 的,所以大家對(duì)于這兩個(gè) map 只需要有個(gè)大概的概念就好呐矾,后面如果真的碰到他們有數(shù)據(jù)苔埋,我們?cè)谠敿?xì)分析。