Objective-C消息轉發機制詳解

消息轉發機制的出現

? ? ? ? ? ? 回想一下,在我們日常的程序開發中,是不是經常會遇到下面這種情況:

自定義的Atom類
示例

? ? ? ? 我們自定義了一個類,然后再程序中調用某個方法,但是這個方法在該類中找不到相應實現,系統提示我們unrecognized selector sent to instance,表明該對象無法解讀此消息,但作為一門高級的編程語言,難道Objective-C不做任何事就會讓程序崩潰掉嗎,答案當然是...不可能!作為一門動態語言,Objective-C充分的利用了它的語言特性,在程序運行期間通過一些方法來給開發者機會阻斷程序這樣的崩潰,給對象和消息更多的機會來完成成功的調用,而這其中所用用到的技術就是消息轉發機制。

什么是消息轉發機制

? ? ? ? 消息轉發機制,聽起來好像很厲害的一個概念,那么消息轉發機制到底是什么意思呢,我的理解是消息轉發機制就是系統為了更好的解決對象收到無法解讀的消息這件事,然后自己創建出的一個模式,包含了一系列方法,就像程序崩潰前的防守陣營一樣,用來阻止程序直接走向崩潰。下面用一張圖來形象的展示一下消息轉發機制的構成:

消息轉發機制

? ? ? ?由圖中可以直觀的看到,消息轉發機制主要包含三個步驟:

? ? ? ? 1:動態方法解析階段

? ? ? ? 2:備用接收者階段

? ? ? ? 3:完整消息轉發階段

? ? ? ? 如果程序經過這三個階段之后都沒能解讀所調用的消息,那么程序會調走向最后的灰色提示,doesNotRecognizeSelector方法,拋出異常,需要注意一點的是,上面三個步驟,越往后,處理消息的代價越大。好啦,下面我們就來具體介紹一下這三個步驟吧!

動態方法解析階段

? ? ? ?這是消息轉發的第一階段,處在這個階段的時候,主要有兩個方法來幫你解決問題:

? ? ? ?1:+(BOOL)resolveClassMethod:(SEL)sel

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

? ? ? 顧名思義,當方法是類方法時調用1,當方法為實例方法時,調用2。這個方法設計的目的是為了給類利用 class_addMethod 添加方法的機會。下面來看一下具體實現的例子:

示例

由代碼可知,在Atom類中我并未定義一個名為instanceTest的實例方法,所以編譯器報了黃色的警告,但我在Atom的實現文件中通過+(BOOL)resolveInstanceMethod:(SEL)sel這個方法在運行時動態的添加了方法的實現,最終程序正常運行。

? ? ? ? 關于class_addMethod(__unsafe_unretained Class cls, SEL name, IMP imp, const char *types)方法:

這里對于這個方法的參數做一點補充:

cls:被添加方法的目標類

name:新方法的選擇器

imp:實現這個方法的函數的地址

types:描述方法參數的數據類型的字符串,例如這個例子中我寫的id functionForInstance(id self,SEL _cmd),就對應“@@:”,這種表達方式叫Type Encodings,是官方定義好的,更全的展示我在這貼兩張官方的圖:

type encodings
method encodings

備用接收者階段

? ? ? ? 這是消息轉發的第二階段,如果第一階段沒有成功,就會來到這個階段,在這個階段主要利用的方法是- (id)forwardingTargetForSelector:(SEL)aSelector,此時,運行時詢問能否把消息轉給其他接收者處理,也就是此時系統給了個將這個 SEL 轉給其他對象的機會,具體示例如圖所示:

示例

我們新定義了一個類,名為Helper,在該類中我們實現了instanceTest實例方法,當系統運行時在Atom類中找不到方法的相應實現,于是來到- (id)forwardingTargetForSelector:(SEL)aSelector這個方法,請求備用者響應,如果備用者能響應則將此消息轉給新對象執行。

完整消息轉發階段

? ? ? 如果前兩個階段都不能解決問題,系統就會來到最后這個第三階段,完整消息轉發階段,這是消息轉發流程的最后一個環節,與第二階段不同,此階段可以將消息轉發給多個對象,這個階段主要利用的方法是- (void)forwardInvocation:(NSInvocation *)anInvocation,但是注意一點,使用這個方法必須同時重寫- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector這個方法,消息轉發機制使用從這個方法中獲取的信息來創建NSInvocation對象,具體示例如圖:

Helper實現文件
Helper2實現文件
Atom實現文件
示例

? ? ? 在這個例子中,我們新建了一個Helper2類,同樣實現了instanceTest實例方法,可以看到,在這個例子中最后程序順利執行了,同時Helper和Helper2都響應了這條消息,同時也能發現,最后的返回值是最后一個處理消息轉發對象的對應方法的返回值。

? ? ?補充一點,關于methodSignatureForSelector,methodSignatureForSelector用于描述被轉發的消息,系統會調用methodSignatureForSelector:方法,嘗試獲得一個方法簽名。如果獲取不到,則直接調用doesNotRecognizeSelector拋出異常。如果能獲取,則返回非nil:創建一個 NSlnvocation 并傳給forwardInvocation:。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,228評論 2 375

推薦閱讀更多精彩內容

  • 轉至元數據結尾創建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 1,753評論 0 9
  • 消息發送和轉發流程可以概括為:消息發送(Messaging)是 Runtime 通過 selector 快速查找 ...
    lylaut閱讀 1,878評論 2 3
  • 我們常常會聽說 Objective-C 是一門動態語言,那么這個「動態」表現在哪呢?我想最主要的表現就是 Obje...
    Ethan_Struggle閱讀 2,227評論 0 7
  • 本文詳細整理了 Cocoa 的 Runtime 系統的知識,它使得 Objective-C 如虎添翼,具備了靈活的...
    lylaut閱讀 818評論 0 4
  • 轉載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 756評論 0 2