load

問題一:Category中有l(wèi)oad方法嗎抽活?

答:有的炊甲,但是和其他方法不同渠鸽,Category 中的load和類中的load方法,并不是簡單的覆蓋或者繼承娇未。用一個簡單的工程可以看出:

LoadClass.m:

#import "LoadClass.h"

@implementation LoadClass

+(void)load{
    
    NSLog(@"Class Load Execute");
}
@end

LoadClass+LoadClassCategory.m:


#import "LoadClass+LoadClassCategory.h"

@implementation LoadClass (LoadClassCategory)

+(void)load{
    NSLog(@"Category Load Execute");
}
@end

輸出:

2019-11-10 20:57:22.986038+0800 LoadDemo[88431:1086125] Class Load Execute
2019-11-10 20:57:22.986486+0800 LoadDemo[88431:1086125] Category Load Execute

從輸出可以看出,并沒有出現(xiàn)方法覆蓋的情況星虹,兩個load方法都被執(zhí)行了零抬。

問題二:load方法是什么時候被調(diào)到的?

要探究這個問題其實很簡單搁凸,只需要在上述代碼中的load方法中下一個斷點媚值,查看調(diào)用堆棧即可:

image.png

程序運行并命中斷點之后,查看輸出:
image.png

這里我們主要看load的上層調(diào)用load_images护糖。顯然這個時候褥芒,我們需要借助runtime源碼去分析。
首先找到這個函數(shù):


/***********************************************************************
* load_images
* Process +load in the given images which are being mapped in by dyld.
*
* Locking: write-locks runtimeLock and loadMethodLock
**********************************************************************/
extern bool hasLoadMethods(const headerType *mhdr);
extern void prepare_load_methods(const headerType *mhdr);

void
load_images(const char *path __unused, const struct mach_header *mh)
{
    // Return without taking locks if there are no +load methods here.
    if (!hasLoadMethods((const headerType *)mh)) return;

    recursive_mutex_locker_t lock(loadMethodLock);

    // Discover load methods
    {
        mutex_locker_t lock2(runtimeLock);
        prepare_load_methods((const headerType *)mh);
    }

    // Call +load methods (without runtimeLock - re-entrant)
    call_load_methods();
}

函數(shù)內(nèi)部其實很簡單嫡良,就是幾個函數(shù)的調(diào)用锰扶,這里,我們主要關注兩個函數(shù)-----prepare_load_methods寝受、call_load_methods坷牛。
先看prepare_load_methods

void prepare_load_methods(const headerType *mhdr)
{
    size_t count, i;

    runtimeLock.assertLocked();

    classref_t *classlist = 
        _getObjc2NonlazyClassList(mhdr, &count);
    for (i = 0; i < count; i++) {
        schedule_class_load(remapClass(classlist[i]));
    }

    category_t **categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
    for (i = 0; i < count; i++) {
        category_t *cat = categorylist[i];
        Class cls = remapClass(cat->cls);
        if (!cls) continue;  // category for ignored weak-linked class
        realizeClass(cls);
        assert(cls->ISA()->isRealized());
        add_category_to_loadable_list(cat);
    }
}

看函數(shù)的內(nèi)部流程和調(diào)用,其實不難看出很澄,prepare_load_methods函數(shù)內(nèi)部遍歷所有類京闰,并調(diào)用schedule_class_load函數(shù),將所有類中的load方法加入列表中甩苛,之后有遍歷所有的category并調(diào)用add_category_to_loadable_list函數(shù)將category中的load方法加入列表中蹂楣。大致的流程就是這樣子的,如果想更深入的研究load方法添加到列表中的細節(jié)讯蒲,可以詳細分析一下這兩個函數(shù)痊土。
接下來看看call_load_methods是怎么調(diào)用load方法的。

/***********************************************************************
* call_load_methods
* Call all pending class and category +load methods.
* Class +load methods are called superclass-first. 
* Category +load methods are not called until after the parent class's +load.
* 
* This method must be RE-ENTRANT, because a +load could trigger 
* more image mapping. In addition, the superclass-first ordering 
* must be preserved in the face of re-entrant calls. Therefore, 
* only the OUTERMOST call of this function will do anything, and 
* that call will handle all loadable classes, even those generated 
* while it was running.
*
* The sequence below preserves +load ordering in the face of 
* image loading during a +load, and make sure that no 
* +load method is forgotten because it was added during 
* a +load call.
* Sequence:
* 1. Repeatedly call class +loads until there aren't any more
* 2. Call category +loads ONCE.
* 3. Run more +loads if:
*    (a) there are more classes to load, OR
*    (b) there are some potential category +loads that have 
*        still never been attempted.
* Category +loads are only run once to ensure "parent class first" 
* ordering, even if a category +load triggers a new loadable class 
* and a new loadable category attached to that class. 
*
* Locking: loadMethodLock must be held by the caller 
*   All other locks must not be held.
**********************************************************************/
void call_load_methods(void)
{
    static bool loading = NO;
    bool more_categories;

    loadMethodLock.assertLocked();

    // Re-entrant calls do nothing; the outermost call will finish the job.
    if (loading) return;
    loading = YES;

    void *pool = objc_autoreleasePoolPush();

    do {
        // 1. Repeatedly call class +loads until there aren't any more
        while (loadable_classes_used > 0) {
            call_class_loads();
        }

        // 2. Call category +loads ONCE
        more_categories = call_category_loads();

        // 3. Run more +loads if there are classes OR more untried categories
    } while (loadable_classes_used > 0  ||  more_categories);

    objc_autoreleasePoolPop(pool);

    loading = NO;
}

根據(jù)代碼和注釋墨林,可以清楚的看出赁酝,load方法的調(diào)用流程為:先調(diào)用類中的load方法犯祠,再調(diào)用類別中的load方法。這其實可以說明一個問題:類中的load方法比類別中的load方法先執(zhí)行酌呆。
到這里衡载,其實咱們就可以回答剛剛的那個問題了:
答:load方法是在類或者類別添加到runtime的時候,被調(diào)用的肪笋,而且其調(diào)用順序是:先類中的load月劈,再類別中的load

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末藤乙,一起剝皮案震驚了整個濱河市猜揪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坛梁,老刑警劉巖而姐,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異划咐,居然都是意外死亡拴念,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門褐缠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來政鼠,“玉大人,你說我怎么就攤上這事队魏」悖” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵胡桨,是天一觀的道長官帘。 經(jīng)常有香客問我,道長昧谊,這世上最難降的妖魔是什么刽虹? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮呢诬,結果婚禮上涌哲,老公的妹妹穿的比我還像新娘。我一直安慰自己尚镰,他們只是感情好膛虫,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钓猬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撩独。 梳的紋絲不亂的頭發(fā)上敞曹,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天账月,我揣著相機與錄音,去河邊找鬼澳迫。 笑死局齿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的橄登。 我是一名探鬼主播抓歼,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拢锹!你這毒婦竟也來了谣妻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卒稳,失蹤者是張志新(化名)和其女友劉穎蹋半,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體充坑,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡减江,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了捻爷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辈灼。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖也榄,靈堂內(nèi)的尸體忽然破棺而出巡莹,到底是詐尸還是另有隱情,我是刑警寧澤手蝎,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布榕莺,位于F島的核電站,受9級特大地震影響棵介,放射性物質(zhì)發(fā)生泄漏钉鸯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一邮辽、第九天 我趴在偏房一處隱蔽的房頂上張望唠雕。 院中可真熱鬧,春花似錦吨述、人聲如沸岩睁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捕儒。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刘莹,已是汗流浹背阎毅。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留点弯,地道東北人扇调。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像抢肛,于是被迫代替她去往敵國和親狼钮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容