iOS 消息轉發(fā)機制Demo解析

消息轉發(fā)機制

假設說我們聲明一個類, 初始化對象, 并且在此類聲明一個方法, 調用方法的時候底層是怎么處理的呢? 今天我們來簡單模擬測試, 來看道理發(fā)生了什么

以下是調用方法處理的方案圖, 按照方案順序去處理

以下是系統(tǒng)方法

//消息轉發(fā)

//-?(id)forwardingTargetForSelector:(SEL)aSelector?OBJC_AVAILABLE(10.5,?2.0,?9.0,?1.0,?2.0);

//標準的消息轉發(fā)

//-?(void)forwardInvocation:(NSInvocation?*)anInvocation?OBJC_SWIFT_UNAVAILABLE("");

//-?(NSMethodSignature?*)methodSignatureForSelector:(SEL)aSelector?OBJC_SWIFT_UNAVAILABLE("");

//

//動態(tài)方法解析

//+?(BOOL)resolveClassMethod:(SEL)sel?OBJC_AVAILABLE(10.5,?2.0,?9.0,?1.0,?2.0);

//+?(BOOL)resolveInstanceMethod:(SEL)sel?OBJC_AVAILABLE(10.5,?2.0,?9.0,?1.0,?2.0);

Demo解析

基礎步驟

創(chuàng)建類, Person類, 聲明方法, 并且在ViewController進行初始化調用

VC中

Person?*person?=?[Personnew];

[person?run];

Person類中

-?(void)run;//沒有實現(xiàn)

此時運行是不是會報錯呢? 就是這個常見的錯誤

“ - [Person run]: unrecognized selector sent to instance 0x600000008310’ “

那么這樣做到底發(fā)生了什么? 做了哪些事情? 我們一步步來剖析

動態(tài)測試

在Presenter類中, 寫動態(tài)方法

+?(BOOL)resolveInstanceMethod:(SEL)sel{

NSLog(@"sel?=?%@",NSStringFromSelector(sel));

return[superresolveInstanceMethod:sel];

}

再次運行Demo就會走到這個方法中, 也就是我們所指的方案1, 此時打印出來的scl為” 消息轉發(fā)機制Demo[41829:4186268] sel = run “

解析模擬

+?(BOOL)resolveInstanceMethod:(SEL)sel{

NSLog(@"sel?=?%@",NSStringFromSelector(sel));

//1.判斷沒有實現(xiàn)方法,?那么我們就是動態(tài)添加一個方法

if(sel?==?@selector(run:))?{

class_addMethod(self,?sel,?(IMP)newRun,"v@:@:");

returnYES;

}

return[superresolveInstanceMethod:sel];

}

聲明函數(shù)

voidnewRun(id?self,SEL?sel,NSString?*str)?{

NSLog(@"---runok---%@",str);

}

溫馨小提示, 動態(tài)添加方法參數(shù)意譯 : //將要添加方法的類/sel名/IMP函數(shù)指針<添加函數(shù)>, 官方文檔其實是有解釋的

此時我們再次運行, 那么打印結果就來了” 消息轉發(fā)機制Demo[43269:4212899] —runok—ok跑 “, 這樣的話我們就解決掉了報錯這個問題

消息轉發(fā)重定向測試

此時我們新創(chuàng)建一個類Mbxb, 此時我們還是重新寫一個同名字的方法run方法, 并且進行實現(xiàn)

-?(void)run{

NSLog(@"---Mbxbrunok---");

}

解析

此時有兩個同樣的方法, 我們重新在Person類中

來實現(xiàn)方法

-?(id)forwardingTargetForSelector:(SEL)aSelector{

NSLog(@"aSelector?=?%@",NSStringFromSelector(aSelector));

return[superforwardingTargetForSelector:aSelector];

}

此時運行測試, 動態(tài)測試輸出” 消息轉發(fā)機制Demo[45875:4255869] sel = run “, 消息轉發(fā)重定向輸出” 消息轉發(fā)機制Demo[45875:4255869] —Mbxbrunok— “, 同樣也可以找見方法run

當我們進行處理

-?(id)forwardingTargetForSelector:(SEL)aSelector{

NSLog(@"aSelector?=?%@",NSStringFromSelector(aSelector));

return[[Mbxb?alloc]init];

}

那么此時運行成功輸出, “ —Mbxbrunok— “

生成方法簽名轉發(fā)消息

此時我們在Person類中, 生成方法簽名

-?(NSMethodSignature?*)methodSignatureForSelector:(SEL)aSelector?OBJC_SWIFT_UNAVAILABLE(""){

//轉化字符

NSString?*sel?=?NSStringFromSelector(aSelector);

//判斷,?手動生成簽名

if([sel?isEqualToString:@"run"]){

return[NSMethodSignature?signatureWithObjCTypes:"v@:"];

}else{

return[supermethodSignatureForSelector:aSelector];

}

拿到簽名

-?(void)forwardInvocation:(NSInvocation?*)anInvocation?OBJC_SWIFT_UNAVAILABLE(""){

NSLog(@"---%@---",anInvocation);

return[superforwardInvocation:anInvocation];

}

此時我們的po的簽名輸出為” return value: {v} void target: {@} 0x600000016ba0 selector: {:} run “

拿到消息轉發(fā)簽名

-?(void)forwardInvocation:(NSInvocation?*)anInvocation?OBJC_SWIFT_UNAVAILABLE(""){

NSLog(@"---%@---",anInvocation);

//取到消息

SEL?seletor?=?[anInvocation?selector];

//轉發(fā)

Mbxb?*bxb?=?[[Mbxb?alloc]init];

if([bxb?respondsToSelector:seletor]){

//調用對象,進行轉發(fā)

[anInvocation?invokeWithTarget:bxb];

}else{

return[superforwardInvocation:anInvocation];

}

}

小細節(jié): 拋出異常

假如說我們沒有這個方法, 同樣是遇到會崩潰的問題

我們這里來進行一個異常處理

-?(void)doesNotRecognizeSelector:(SEL)aSelector{

NSString?*selStr?=?NSStringFromSelector(aSelector);

NSLog(@"%@不存在",selStr);

}

我們可以在這個異常處理中一些處理, 比如說彈框

總結

對于消息轉發(fā)機制, 我們重新來梳理一下Demo解析思路

還是三個方案, 按順序來走

動態(tài)方法解析

消息轉發(fā)重定向

生成方法簽名

拿到簽名轉發(fā)消息

細節(jié)處理, 拋出異常

最后獻上一張邏輯圖

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末晚凿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子猬错,更是在濱河造成了極大的恐慌洞豁,老刑警劉巖禽翼,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異族跛,居然都是意外死亡闰挡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門礁哄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來长酗,“玉大人,你說我怎么就攤上這事桐绒《崞ⅲ” “怎么了之拨?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咧叭。 經(jīng)常有香客問我蚀乔,道長,這世上最難降的妖魔是什么菲茬? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任吉挣,我火速辦了婚禮,結果婚禮上婉弹,老公的妹妹穿的比我還像新娘睬魂。我一直安慰自己,他們只是感情好镀赌,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布氯哮。 她就那樣靜靜地躺著,像睡著了一般商佛。 火紅的嫁衣襯著肌膚如雪喉钢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天良姆,我揣著相機與錄音出牧,去河邊找鬼。 笑死歇盼,一個胖子當著我的面吹牛舔痕,可吹牛的內容都是我干的。 我是一名探鬼主播豹缀,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼伯复,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了邢笙?” 一聲冷哼從身側響起啸如,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎氮惯,沒想到半個月后叮雳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡妇汗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年帘不,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杨箭。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡寞焙,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情捣郊,我是刑警寧澤辽狈,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站呛牲,受9級特大地震影響刮萌,放射性物質發(fā)生泄漏。R本人自食惡果不足惜娘扩,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一着茸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧畜侦,春花似錦、人聲如沸躯保。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽途事。三九已至验懊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尸变,已是汗流浹背义图。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留召烂,地道東北人碱工。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像奏夫,于是被迫代替她去往敵國和親怕篷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容

  • 消息轉發(fā)機制 原文鏈接 : 原文假設說我們聲明一個類, 初始化對象, 并且在此類聲明一個方法, 調用方法的時...
    a437e8f87a81閱讀 543評論 0 0
  • 轉至元數(shù)據(jù)結尾創(chuàng)建: 董瀟偉酗昼,最新修改于: 十二月 23, 2016 轉至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,682評論 0 9
  • 對象在收到無法解讀的消息會發(fā)生什么? 若想令類理解某條消息,必須有對應的實現(xiàn)方法.但是,在編譯期間動態(tài)像對象添加方...
    有一種再見叫青春閱讀 567評論 0 2
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言廊谓,那么這個「動態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,176評論 0 7
  • 在被裁員一個月之后麻削,我衡量了所有的選擇蒸痹,最終決定暫時離開北京。自2006年畢業(yè)以后拖著一個行李箱來北京之后呛哟,再艱難...
    呂賀薇薇閱讀 490評論 0 0