【runtime學(xué)習(xí)之旅】category的方法調(diào)用順序

1.category和原始類中的+(void)load;的調(diào)用順序

先說結(jié)論喜最,調(diào)用順序是先調(diào)用原始類的load方法庄蹋,再去調(diào)用category的load方法限书。為什么呢?


//person class
#import "Person.h"
#import "Person+A.h"
#import "Person+B.h"

@implementation Person
+ (void)load {
    [Person test];
    NSLog(@"load person");
}
+ (void)test {
    NSLog(@"wakakak");
}
@end

//Person+A class
#import "Person+A.h"

@implementation Person (A)
+ (void)load {
    NSLog(@"load person A");
}
+ (void)test {
    NSLog(@"wo shi A");
}
@end

打印結(jié)果:

wo shi A
load person
load person B
load person A

結(jié)果卻是讓我疑惑不解能真,按理說category的方法“覆蓋”原始類方法是基本常識,但load方法卻全部的類都調(diào)用了疼约。這是為啥蝙泼?
大神的扒皮過程 分類的本質(zhì)

runtime的源碼入手:

1.找到objc-os.mm這個文件,然后找到這個文件的void _objc_init(void)這個方法织鲸,runtime的初始化都是在這個方法里面完成茎活。

2.這個方法的最后一行調(diào)用了函數(shù)_dyld_objc_notify_register(&map_images, load_images, unmap_image);,我們點進load_images,這是加載模塊的意思盾饮。

image
image
image
image
image

那么這樣我們就搞清楚了為什么load方法不是像test方法一樣,執(zhí)行分類的實現(xiàn)

因為load方法的調(diào)用并不是objc_msgSend機制徘钥,它是直接找到類的load方法的地址肢娘,然后調(diào)用類的load方法,然后再找到分類的load方法的地址橱健,再去調(diào)用它。所以看起來臼节,他們的load方法都被調(diào)用了珊皿。但其它的方法,例如分裂和父類都寫了test方法粉臊,并且在父類里導(dǎo)入分類驶兜,那么這時候調(diào)用情況是什么果元?

而test方法是通過消息機制去調(diào)用的犀盟。首先找到類對象蝇狼,由于test方法是類方法迅耘,存儲在元類對象中,所以通過類對象的isa指針找到元類對象颤专,然后在元類對象中尋找test方法春塌,由于分類也實現(xiàn)了test方法只壳,所以分類的test方法是在類的test方法的前面暑塑,首先找到了分類的test方法,然后去調(diào)用它惕艳。

總結(jié):
1.先調(diào)用類的load方法
按照編譯先后順序調(diào)用(先編譯驹愚,先調(diào)用)
調(diào)用子類的load方法之前會先調(diào)用父類的load方法

2.再調(diào)用分類的load方法
按照編譯先后順序,先編譯终娃,先調(diào)用蒸甜。順序依據(jù)build phases-》compile sources中分類的順序決定先后。

一般性方法窍荧,如果分類和原始類中都有恨憎,那么根據(jù)objc_msgSend的原理郊楣,根據(jù)runtime的消息傳遞機制中的核心函數(shù)void objc_msgSend(id self,SEL cmd,...)來發(fā)送消息瓤荔,先從當(dāng)前類中查找調(diào)用的方法,若沒有找到則繼續(xù)從其父類中一層層往上找今瀑,那么對于category重寫同一個方法点把,則在消息傳遞的過程中,會最先找到category中的方法并執(zhí)行該方法哥童。對于多個分類調(diào)用同一個方法褒翰,Xcode在運行時是根據(jù)buildPhases->Compile Sources里面的從上至下順序編譯的,編譯時通過壓棧的方式將多個分類壓棧错邦,根據(jù)后進先出的原則型宙,后編譯的會被先調(diào)用,(插入頂部添加魂拦,即[methodLists insertObject:category_method atIndex:0]; 所以objc_msgSend遍歷方法列表查找SEL 對應(yīng)的IMP時搁嗓,會先找到分類重寫的那個,調(diào)用執(zhí)行)當(dāng)objc_msgSend找到方法并調(diào)用之后荷愕,就不再繼續(xù)傳遞消息棍矛,所以形成所謂的覆蓋。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荐类,一起剝皮案震驚了整個濱河市茁帽,隨后出現(xiàn)的幾起案子屈嗤,更是在濱河造成了極大的恐慌饶号,老刑警劉巖璧亚,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件癣蟋,死亡現(xiàn)場離奇詭異狰闪,居然都是意外死亡,警方通過查閱死者的電腦和手機幔欧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門丽声,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浴井,你說我怎么就攤上這事霉撵。” “怎么了撕氧?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵伦泥,是天一觀的道長锦溪。 經(jīng)常有香客問我,道長海洼,這世上最難降的妖魔是什么域帐? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任肖揣,我火速辦了婚禮龙优,結(jié)果婚禮上彤断,老公的妹妹穿的比我還像新娘宰衙。我一直安慰自己供炼,他們只是感情好袋哼,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疫蔓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滚躯。 梳的紋絲不亂的頭發(fā)上茁影,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音浩螺,去河邊找鬼要出。 笑死患蹂,一個胖子當(dāng)著我的面吹牛传于,可吹牛的內(nèi)容都是我干的格了。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼石抡,長吁一口氣:“原來是場噩夢啊……” “哼啰扛!你這毒婦竟也來了隐解?” 一聲冷哼從身側(cè)響起煞茫,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钦扭,沒想到半個月后其弊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瑞凑,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了劲阎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悯仙。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖货岭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情搞坝,我是刑警寧澤己沛,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站垫桂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏霹粥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一庙曙、第九天 我趴在偏房一處隱蔽的房頂上張望浩淘。 院中可真熱鬧,春花似錦张抄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轻猖。三九已至稻爬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間琉雳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留被丧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓甥桂,卻偏偏與公主長得像邮旷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子办陷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

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