Cocoa 之消息

了解三個概念Class, SEL, IMP跟畅,它們在objc/objc.h 中定義:

typedef struct objc_class *Class;

typedef struct objc_object {

    Class isa;

} *id;

typedef struct objc_selector   *SEL;   

typedef id (*IMP)(id, SEL, ...);
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

Class 是指向類結(jié)構(gòu)體的指針咽筋,該類結(jié)構(gòu)體含有一個指向其父類類結(jié)構(gòu)的指針,該類方法的鏈表徊件,該類方法的緩存以及其他必要信息奸攻。

NSObject 的class 方法就返回這樣一個指向其類結(jié)構(gòu)的指針。每一個類實例對象的第一個實例變量是一個指向該對象的類結(jié)構(gòu)的指針虱痕,叫做isa睹耐。通過該指針,對象可以訪問它對應(yīng)的類以及相應(yīng)的父類部翘。如圖一所示:

class superclass.gif

如圖一所示硝训,圓形所代表的實例對象的第一個實例變量為 isa,它指向該類的類結(jié)構(gòu) The object’s class新思。而該類結(jié)構(gòu)有一個指向其父類類結(jié)構(gòu)的指針superclass窖梁, 以及自身消息名稱(selector)/實現(xiàn)地址(address)的方法鏈表。

方法的含義:
注意這里所說的方法鏈表里面存儲的是Method 類型的夹囚。圖一中selector 就是指 Method的 SEL, address就是指Method的 IMP纵刘。 Method 在頭文件 objc_class.h中定義如下:

typedef struct objc_method *Method;

typedef struct objc_ method {

    SEL method_name;

    char *method_types;

    IMP method_imp;

};

方法 Method,其包含
一個 SEL – 表示該方法的名稱荸哟,
一個types – 表示該方法參數(shù)的類型假哎,
一個 IMP - 指向該方法的具體實現(xiàn)的函數(shù)指針

不同的類可以擁有相同的 selector鞍历,這個沒有問題舵抹,因為不同類的實例對象performSelector相同的 selector 時,會在各自的消息選標(biāo)(selector)/實現(xiàn)地址(address) 方法鏈表中根據(jù) selector 去查找具體的方法實現(xiàn)IMP, 然后用這個方法實現(xiàn)去執(zhí)行具體的實現(xiàn)代碼堰燎。這是一個動態(tài)綁定的過程掏父,在編譯的時候,我們不知道最終會執(zhí)行哪一些代碼秆剪,只有在執(zhí)行的時候赊淑,通過selector去查詢,我們才能確定具體的執(zhí)行代碼仅讽。

IMP 的含義:
在前面我們也看到 IMP 的定義為:
typedef id (*IMP)(id, SEL, ...);

至此陶缺,我們就很清楚地知道 IMP 的含義:IMP 是一個函數(shù)指針,這個被指向的函數(shù)包含一個接收消息的對象id(self 指針), 調(diào)用方法的選標(biāo) SEL (方法名)洁灵,以及不定個數(shù)的方法參數(shù)饱岸,并返回一個id掺出。也就是說 IMP 是消息最終調(diào)用的執(zhí)行代碼,是方法真正的實現(xiàn)代碼 苫费。我們可以像在C語言里面一樣使用這個函數(shù)指針汤锨。

消息傳遞(Messaging)

在 Objective-C 中,[object foo]語法并不會立即執(zhí)行 foo 這個方法的代碼百框。它是在運行時給 object 發(fā)送一條叫 foo 的消息闲礼。這個消息,也許會由 object 來處理铐维,也許會被轉(zhuǎn)發(fā)給另一個對象柬泽,或者不予理睬假裝沒收到這個消息。多條不同的消息也可以對應(yīng)同一個方法實現(xiàn)嫁蛇。這些都是在程序運行的時候決定的锨并。

從這些定義中可以看出發(fā)送一條消息也就 objc_msgSend做了什么事。舉 objc_msgSend(obj, foo)
這個例子來說:
1.首先睬棚,通過 obj 的 isa 指針找到它的 class ;
2.在 class 的 method list 找 foo ;
3.如果 class 中沒到 foo第煮,繼續(xù)往它的 superclass 中找 ;
4.一旦找到 foo 這個函數(shù),就去執(zhí)行它的實現(xiàn)IMP .

但這種實現(xiàn)有個問題闸拿,效率低空盼。但一個 class 往往只有 20% 的函數(shù)會被經(jīng)常調(diào)用,可能占總調(diào)用次數(shù)的 80% 新荤。每個消息都需要遍歷一次 objc_method_list并不合理揽趾。如果把經(jīng)常被調(diào)用的函數(shù)緩存下來,那可以大大提高函數(shù)查詢的效率苛骨。這也就是 objc_class中另一個重要成員 objc_cache做的事情 - 再找到 foo 之后篱瞎,把 foo 的 method_name作為 key ,method_imp作為 value 給存起來痒芝。當(dāng)再次收到 foo 消息的時候俐筋,可以直接在 cache 里找到,避免去遍歷 objc_method_list.

首先严衬,編譯器將代碼[obj makeText];轉(zhuǎn)化為objc_msgSend(obj, @selector (makeText));澄者,在objc_msgSend函數(shù)中。首先通過obj的isa指針找到obj對應(yīng)的class请琳。在Class中先去cache中 通過SEL查找對應(yīng)函數(shù)method(猜測cache中method列表是以SEL為key通過hash表來存儲的粱挡,這樣能提高函數(shù)查找速度),若 cache中未找到俄精。再去methodList中查找询筏,若methodlist中未找到,則取superClass中查找竖慧。若能找到嫌套,則將method加 入到cache中逆屡,以方便下次查找,并通過method中的函數(shù)指針跳轉(zhuǎn)到對應(yīng)的函數(shù)中去執(zhí)行踱讨。

參考:
http://blog.csdn.net/kesalin/article/details/6689226

http://southpeak.github.io/blog/2014/10/25/objective-c-runtime-yun-xing-shi-zhi-lei-yu-dui-xiang/

http://tech.glowing.com/cn/objective-c-runtime/

http://blog.csdn.net/a19860903/article/details/44853841

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末魏蔗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子勇蝙,更是在濱河造成了極大的恐慌沫勿,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件味混,死亡現(xiàn)場離奇詭異,居然都是意外死亡诫惭,警方通過查閱死者的電腦和手機翁锡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夕土,“玉大人馆衔,你說我怎么就攤上這事≡剐澹” “怎么了角溃?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長篮撑。 經(jīng)常有香客問我减细,道長,這世上最難降的妖魔是什么赢笨? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任未蝌,我火速辦了婚禮,結(jié)果婚禮上茧妒,老公的妹妹穿的比我還像新娘萧吠。我一直安慰自己,他們只是感情好桐筏,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布纸型。 她就那樣靜靜地躺著,像睡著了一般梅忌。 火紅的嫁衣襯著肌膚如雪狰腌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天铸鹰,我揣著相機與錄音癌别,去河邊找鬼。 笑死蹋笼,一個胖子當(dāng)著我的面吹牛展姐,可吹牛的內(nèi)容都是我干的躁垛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼圾笨,長吁一口氣:“原來是場噩夢啊……” “哼教馆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起擂达,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤土铺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后板鬓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悲敷,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年俭令,在試婚紗的時候發(fā)現(xiàn)自己被綠了后德。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡抄腔,死狀恐怖瓢湃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赫蛇,我是刑警寧澤绵患,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站悟耘,受9級特大地震影響落蝙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜作煌,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一掘殴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粟誓,春花似錦奏寨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悲酷,卻和暖如春套菜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背设易。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工逗柴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人顿肺。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓戏溺,卻偏偏與公主長得像渣蜗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子旷祸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉耕拷,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,715評論 0 9
  • 在入門級別的ObjC 教程中,我們常對從C++或Java 或其他面向?qū)ο笳Z言轉(zhuǎn)過來的程序員說托享,ObjC 中的方法調(diào)...
    Mr_Baymax閱讀 255評論 4 3
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言骚烧,那么這個「動態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,193評論 0 7
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,556評論 33 466
  • 如果可以可不可以放縱一下自己 如果可以可不可以消極地隱居山林 如果可以可不可以不再拼搏 如果可以可不可以只做自己喜...
    紫玉云瀟閱讀 236評論 0 1