Objective-C消息發(fā)送

一 概述:
Objective-C(簡(jiǎn)稱OC)的Cocoa層的API中有大量的[receiver message]消息發(fā)送機(jī)制,初學(xué)時(shí)我們往往把理解為一個(gè)object調(diào)用了一個(gè)method,而往往忽視了"消息機(jī)制"這句話的深刻含義,[receiver message]獨(dú)特機(jī)制區(qū)別于其他主流語(yǔ)言.
二 原理:
消息發(fā)送機(jī)制是Runtime通過(guò)selector快速查找IMP的過(guò)程,有了IMP這個(gè)函數(shù)指針,就可以執(zhí)行對(duì)應(yīng)的方法實(shí)現(xiàn).
[receiver message]會(huì)被編譯器轉(zhuǎn)換成為:
// arg1 ,arg2... 表示消息含有的參數(shù)
objc_msgSend(receiver, selector, arg1, arg2, ...)

如果消息的接受者能夠找到對(duì)應(yīng)的selector,相當(dāng)于執(zhí)行了這個(gè)對(duì)象方法,否則消息要么被轉(zhuǎn)發(fā),要么臨時(shí)向接受者動(dòng)態(tài)添加這個(gè) selector 對(duì)應(yīng)的實(shí)現(xiàn)內(nèi)容,要么就干脆崩潰.

63626262e6effdd824dcdc6b20ce3e36.png

那么儡循,objc.msgSend又是怎么確定應(yīng)該調(diào)用哪個(gè)方法的呢软啼?它有一個(gè)動(dòng)態(tài)查找過(guò)程烛愧,具體如下:
①在相應(yīng)對(duì)象的緩存方法列表中( objc_class的cache )查找調(diào)用的方法
②如果沒找到工腋,則在相應(yīng)對(duì)象的方法列表中找調(diào)用方法
③如果還沒找到色难,就到父類指針指向的對(duì)象中執(zhí)行①和②兩步蝴簇。



 // 給 stuModel對(duì)象發(fā)送一個(gè)messageSender消息 在.h中不聲明 objc_msgSend/messageSender也可以發(fā)送消息給stuModel xcode 會(huì)有警告
    objc_msgSend(stuModel, @selector(messageSender
    
    // 帶參數(shù)
    objc_msgSend(stuModel, @selector(messageSender:),@"hello runtime");

IMP:定義為 typedef void (*IMP)(void /* id,SEL,... */);本質(zhì)是個(gè)函數(shù)指針,由編譯器生成,當(dāng)發(fā)送一條消息之后,最終它會(huì)執(zhí)行方法,就是由該函數(shù)指針定的,而IMP這個(gè)函數(shù)指針就是指向了這個(gè)方法的實(shí)現(xiàn).IMP指針方法實(shí)現(xiàn)和SEL一一對(duì)應(yīng)的.

三 super
super是OC的保留字,不是隱式參數(shù),它只是個(gè)''編譯器指示器',主要是針對(duì)父類
id objc_msgSendSuper(struct objc_super *super,SEL op,...)
當(dāng)消息傳遞給父類的時(shí)候,調(diào)用objc_msgSendSuper,objc_super 這個(gè)結(jié)構(gòu)體會(huì)存放當(dāng)前函數(shù)里的self(隱式參數(shù))的super_class,即[self superclass];msgSendSuper從當(dāng)前對(duì)象的父類方法開始,沿著父類繼承鏈查找.最終執(zhí)行到[super respondsToSelector:@selector(superHasNotThisSelector) ]; 而respondsToSelector這個(gè)方法是NSObject方法,而NSObjcet類位于所有類繼承的頂端,執(zhí)行這個(gè)方法會(huì)找到對(duì)應(yīng)的實(shí)現(xiàn)函數(shù)!
四 self
self是OC的隱式參數(shù),之所以叫隱式參數(shù)是因?yàn)樵创a方法定義中并沒有聲明這個(gè)參數(shù),但我們可以引用它;self本身也是個(gè)指針,在每個(gè)方法中都有一個(gè)self指針,在函數(shù)中無(wú)法使用,可以使用self -> 成員變量
五 動(dòng)態(tài)方法
前面提到某些情況下消息的接受者無(wú)法找到對(duì)應(yīng)的selector時(shí),會(huì)臨時(shí)向接受者動(dòng)態(tài)添加這個(gè)selector對(duì)應(yīng)的實(shí)現(xiàn)內(nèi)容.
給某個(gè)屬性聲明@dynamic類型,編譯器會(huì)認(rèn)為這個(gè)屬性相關(guān)的方法會(huì)動(dòng)態(tài)提供,也就是說(shuō)編譯器不會(huì)默認(rèn)生成屬性的setget方法了,而需要我們動(dòng)態(tài)提供,可以通過(guò)重載resolveInstanceMethod:resolveClassMethod添加動(dòng)態(tài)方法.
代碼示例如下:

#import <Foundation/Foundation.h>

@interface AutoMehtodModel : NSObject
@property(nonatomic,copy)NSString *addAutoMethod;

@end
#import "AutoMehtodModel.h"
#import <objc/runtime.h>
@implementation AutoMehtodModel
@dynamic addAutoMethod;
/**
  為addAutoMethod動(dòng)態(tài)添加set和get方法
 **/
 +(BOOL)resolveInstanceMethod:(SEL)sel
{
    NSString *addSelectorStr = NSStringFromSelector(sel);
    //v@:@是一種符合 涉及到https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
    if ([addSelectorStr isEqualToString:@"setAddAutoMethod:"]) {
        class_addMethod(self, sel, (IMP)autoSetter, "v@:@");
    }else if ([addSelectorStr isEqualToString:@"addAutoMethod"]){
        class_addMethod(self, sel, (IMP)autoGet, "@@:");
    }
    return [super resolveInstanceMethod:sel];
}

void autoSetter(id self,SEL _cmd, id value){
    NSLog(@"set方法 === %@",value);
    
}

id autoGet(id self,SEL _cmd){
    return @"get方法";
}
 AutoMehtodModel *model = [[AutoMehtodModel alloc]init];
    model.addAutoMethod   = @"動(dòng)態(tài)方法";
    NSLog(@"%@",model.addAutoMethod);

運(yùn)行結(jié)果:

2018-03-27 10:53:07.875514+0800 OC_Categroy[962:61285] set方法 === 動(dòng)態(tài)方法
2018-03-27 10:53:23.157687+0800 OC_Categroy[962:61285] get方法

參考文獻(xiàn):http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末世曾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子霹抛,更是在濱河造成了極大的恐慌搓逾,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杯拐,死亡現(xiàn)場(chǎng)離奇詭異霞篡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)端逼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門朗兵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人裳食,你說(shuō)我怎么就攤上這事矛市≤搅ぃ” “怎么了诲祸?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)而昨。 經(jīng)常有香客問我救氯,道長(zhǎng),這世上最難降的妖魔是什么歌憨? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任着憨,我火速辦了婚禮,結(jié)果婚禮上务嫡,老公的妹妹穿的比我還像新娘甲抖。我一直安慰自己漆改,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布准谚。 她就那樣靜靜地躺著挫剑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪柱衔。 梳的紋絲不亂的頭發(fā)上樊破,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音唆铐,去河邊找鬼哲戚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛艾岂,可吹牛的內(nèi)容都是我干的顺少。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼王浴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼祈纯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起叼耙,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤腕窥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后筛婉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體簇爆,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年爽撒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了入蛆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硕勿,死狀恐怖哨毁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情源武,我是刑警寧澤扼褪,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站粱栖,受9級(jí)特大地震影響话浇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜闹究,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一幔崖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦赏寇、人聲如沸吉嫩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)率挣。三九已至,卻和暖如春露戒,著一層夾襖步出監(jiān)牢的瞬間椒功,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工智什, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留动漾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓荠锭,卻偏偏與公主長(zhǎng)得像旱眯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子证九,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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