從方法執(zhí)行過程看rumtine/message機(jī)制

簡介

Objective-C是開發(fā)蘋果軟件的語言, 大部分是C語言.除去一些基本的特性, 最重要的它是一門動態(tài)語言, 其動態(tài)性的基石便是rumtime, 即運(yùn)行時機(jī)制.可以說OC沒有運(yùn)行時就沒有了魅力.

消息機(jī)制

對于靜態(tài)語言, 執(zhí)行方法顯得比較死,方法名就能決定了此次方法執(zhí)行的全部因素, 但是對于消息分發(fā)機(jī)制來說,就很靈活。編譯階段一切都是未定的, 并不知道對象是否能處理, 也不知道最終是哪個對象處理, 也不知道最終調(diào)用的方法實現(xiàn)是什么, 而這一切都是在運(yùn)行時決定.

下面我們來詳細(xì)剖析一下方法調(diào)用的整個的過程

- (void)viewDidLoad {
    [super viewDidLoad];

    Dog *dog = [[Dog alloc] init];
    [dog doSomething];
}

[dog doSomething]

  1. [dog doSomething]干了什么?
    編譯器將
    [dog doSomething] --->
    objc_msgSend(dog, @selector(doSomething))

  2. objc_msgSend(dog, @selector(doSomething)) 干了什么?這是重點(diǎn), 詳細(xì)講解:

    1. 檢查dog是個什么類型的對象,即查找dog的Class, OC對象本身有一個isa成員, 這個isa決定了對象的類型, 即isa指針?biāo)赶虻腃lass是dog的真實類型, 而不在乎用什么類型的指針接收這個對象, 這是多態(tài)的基礎(chǔ).
    • 這一步可以玩的花樣:
      如果在 [dog doSomething]這句代碼執(zhí)行之前(注意一定要之前), 改變dog的isa指針的指向, 改為 Cat 類型, 那么處理這條消息的對象就不是Dog類型了, 而是Cat類型. OC中KVO就是用這種方式來實現(xiàn)的, 可以看我這篇文章KVO的原理, 底層實現(xiàn).
    1. OC中class維護(hù)一份方法列表objc_method_list,
      這個列表中存放著SEL, 即相當(dāng)于方法名, 也可以說是方法的id. 這一步系統(tǒng)會查找class中objc_method_list中有沒有doSomething, 如果沒有則向其superclass的objc_method_list中去查找.
    • 這一步可以玩的花樣:
      同理在這一步之前, 即使沒有顯式的doSomething方法聲明和實現(xiàn), 只要利用class_addMethod來動態(tài)添加doSomething方法即可. 但是需要用到performSelector相關(guān)的方法來調(diào)用以保證編譯通過.
    1. 找到doSomething這個SEL之后, 系統(tǒng)就會調(diào)用, 注意, 這個SEL仍然不能決定系統(tǒng)最終執(zhí)行的代碼是什么, 決定者是與SEL有映射關(guān)系的IMP, 簡單說每一個SEL只相當(dāng)于一個字典的key, 這個key所對應(yīng)的value才真正決定了方法的實現(xiàn), 這一步只是系統(tǒng)通過SEL去找到這個value, 這個value就是IMP, IMP是一個函數(shù)指針, 指向方法的實現(xiàn), IMP決定了最終調(diào)用哪段代碼.
    • 這一步可以玩的花樣:
      在函數(shù)執(zhí)行之前, 如果改變了doSomething 這個SEL對應(yīng)的IMP, 改為另一個方法eat的IMP, 那么這句[dog doSomething]最終的結(jié)果是 dog 執(zhí)行了 eat 的實現(xiàn). method_exchangeImplementations這個函數(shù)便是通過這種方式來做到方法交換的.

從上面可以看到一句編譯階段的[dog doSomething]基本決定不了任何東西, 在以上運(yùn)行過程中隨意改變一些東西,就可以使[dog doSomething]"面目全非". 這也是rumtime強(qiáng)大的地方.

覺得有用的的猿友點(diǎn)個贊!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末焰盗,一起剝皮案震驚了整個濱河市糠涛,隨后出現(xiàn)的幾起案子靖榕,更是在濱河造成了極大的恐慌欧聘,老刑警劉巖根吁,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件员淫,死亡現(xiàn)場離奇詭異,居然都是意外死亡击敌,警方通過查閱死者的電腦和手機(jī)介返,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沃斤,“玉大人圣蝎,你說我怎么就攤上這事『馄浚” “怎么了徘公?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長哮针。 經(jīng)常有香客問我关面,道長坦袍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任等太,我火速辦了婚禮捂齐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缩抡。我一直安慰自己奠宜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布缝其。 她就那樣靜靜地躺著挎塌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪内边。 梳的紋絲不亂的頭發(fā)上榴都,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機(jī)與錄音漠其,去河邊找鬼嘴高。 笑死,一個胖子當(dāng)著我的面吹牛和屎,可吹牛的內(nèi)容都是我干的拴驮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柴信,長吁一口氣:“原來是場噩夢啊……” “哼套啤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起随常,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤潜沦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后绪氛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唆鸡,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年枣察,在試婚紗的時候發(fā)現(xiàn)自己被綠了争占。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡序目,死狀恐怖臂痕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宛琅,我是刑警寧澤刻蟹,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站嘿辟,受9級特大地震影響舆瘪,放射性物質(zhì)發(fā)生泄漏片效。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一英古、第九天 我趴在偏房一處隱蔽的房頂上張望淀衣。 院中可真熱鬧,春花似錦召调、人聲如沸膨桥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽只嚣。三九已至,卻和暖如春艺沼,著一層夾襖步出監(jiān)牢的瞬間册舞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工障般, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留调鲸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓挽荡,卻偏偏與公主長得像藐石,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子定拟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

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