分類與原類方法名相同的方法編譯順序

一 ??????準(zhǔn)備工作:

搭建環(huán)境,新建Person類,并給Person類添加A,B,C三個(gè)分類。

二 測(cè)試????與結(jié)論:

  • 1.主類和三個(gè)分類分別添加+ (void)load方法;
///Person.m
+ (void)load {
   NSLog(@"load Person");
}
///Person+A.m
+ (void)load {
   NSLog(@"load Person A");
}
///Person+B.m
+ (void)load {
   NSLog(@"load Person B");
}
///Person+C.m
+ (void)load {
   NSLog(@"load Person C");
}
///ViewController.m
#import "Person.h"
- (void)viewDidLoad {
   [super viewDidLoad];
   Person *p = [[Person alloc] init];
}

運(yùn)行項(xiàng)目后,輸出結(jié)果:

load Person
load Person C
load Person B
load Person A

初步可以有以下結(jié)論:+load方法的優(yōu)先級(jí): 父類> 分類,那么分類的優(yōu)先級(jí)是怎么樣的呢?

我們調(diào)整分類的編譯順序:

運(yùn)行項(xiàng)目后,輸出結(jié)果:

load Person
load Person B
load Person A
load Person C

結(jié)果發(fā)現(xiàn):分類優(yōu)先級(jí)為編譯的順序,從上到下;

結(jié)論:在分類重寫(xiě)load方法時(shí), load方法不會(huì)被覆蓋;優(yōu)先級(jí):父類> 分類(優(yōu)先級(jí)為編譯的順序,從上到下)。

  • 2.主類和三個(gè)分類分別添加和- (NSString *)getAge方法(方法名在分類和主類一樣會(huì)報(bào)警告, 不會(huì)報(bào)錯(cuò));
///Person.m
- (NSString *)getAge {
   return @"Person age";
}
+ (void)load {
   NSLog(@"load Person");
}
///Person+A.m
- (NSString *)getAge {
   return @"Person A age";
}
+ (void)load {
   NSLog(@"load Person A");
}
///Person+B.m
- (NSString *)getAge {
   return @"Person B age";
}
+ (void)load {
   NSLog(@"load Person B");
}
///Person+C.m
- (NSString *)getAge {
   return @"Person C age";
}
+ (void)load {
   NSLog(@"load Person C");
}
///ViewController.m
#import "Person.h"
- (void)viewDidLoad {
   [super viewDidLoad];
   Person *p = [[Person alloc] init];
   NSString *age = [p getAge];
   NSLog(@"%@", age);
}

運(yùn)行項(xiàng)目后,輸出結(jié)果:

load Person
load Person B
load Person A
load Person C
Person C age

在buildPhases->Compile Sources里進(jìn)行位置變換,發(fā)現(xiàn)只會(huì)調(diào)用最后編譯的分類方法。從而得出普通方法的優(yōu)先級(jí): 分類> 父類, 優(yōu)先級(jí)高(分類)的同名方法覆蓋優(yōu)先級(jí)低的,分類覆蓋其他分類。

三 原理

根據(jù)runtime的消息傳遞機(jī)制中的核心函數(shù)void objc_msgSend(id self,SEL cmd,...)來(lái)發(fā)送消息,先從當(dāng)前類中查找調(diào)用的方法,若沒(méi)有找到則繼續(xù)從其父類中一層層往上找,那么對(duì)于category重寫(xiě)同一個(gè)方法,則在消息傳遞的過(guò)程中,會(huì)最先找到category中的方法并執(zhí)行該方法。
對(duì)于多個(gè)分類實(shí)現(xiàn)同一個(gè)方法,Xcode在運(yùn)行時(shí)是根據(jù)buildPhases->Compile Sources里面的從上至下順序編譯的,編譯時(shí)通過(guò)壓棧的方式將多個(gè)分類壓棧,根據(jù)后進(jìn)先出的原則,后編譯的會(huì)被先調(diào)用,(從頂部添加,即[methodLists insertObject:category_method atIndex:0]; 所以objc_msgSend遍歷方法列表查找SEL 對(duì)應(yīng)的IMP時(shí),會(huì)先找到分類重寫(xiě)的那個(gè),調(diào)用執(zhí)行)當(dāng)objc_msgSend找到方法并調(diào)用之后,就不再繼續(xù)傳遞消息,所以形成所謂的覆蓋。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容