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,這是加載模塊的意思盾饮。
那么這樣我們就搞清楚了為什么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ù)傳遞消息棍矛,所以形成所謂的覆蓋。