Runtime

Runtime是什么

將一些在編譯、鏈接過程中的工作,放到運(yùn)行階段声登,因此Objective-C為動(dòng)態(tài)語言

Runtime是一個(gè)庫格遭,這個(gè)庫使我們可以在程序運(yùn)行時(shí)創(chuàng)建對象哈街、檢查對象、修改類和對象的方法拒迅。

Runtime是怎么工作的

Class和Object

objc.h中骚秦,Class被定義為指向objc_class的指針她倘,定義如下:

typedef struct objc_class *Class;

objc_class是一個(gè)結(jié)構(gòu)體,在runtime.h中的定義如下:

struct objc_class {
    // isa指針指向的類結(jié)構(gòu)稱為metaclass作箍,其中存放著static類型的成員變量與static類型的方法(“+”開頭的方法)
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    // 指向該類的父類的指針硬梁,如果該類是根類(如NSObject或NSProxy),那么super_class就為nil胞得。
    Class super_class                                        OBJC2_UNAVAILABLE; // 父類
    const char *name                                         OBJC2_UNAVAILABLE; // 類名
    long version                                             OBJC2_UNAVAILABLE; // 類的版本信息荧止,可以通過runtime函數(shù)class_setVersion或者class_getVersion進(jìn)行修改、讀取
    long info                                                OBJC2_UNAVAILABLE; // 類信息阶剑,供運(yùn)行時(shí)期使用的一些位標(biāo)識跃巡、如CLS_CLASS(0x1L)表示該類為普通 class,其中包含實(shí)例方法和變量牧愁;CLS_META(0x2L)表示該類為metaclass素邪,其中包含類方法;
    long instance_size                                       OBJC2_UNAVAILABLE; // 該類的實(shí)例變量大兄戆搿(包括從父類繼承下來的實(shí)例變量)
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE; // 該類的成員變量地址列表
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE; // 方法的地址列表兔朦,與info的一些標(biāo)識位有關(guān),如CLS_CLASS(0x1L)則存儲實(shí)例方法磨确,如CLS_META(0x2L)沽甥,則存儲類方法;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE; // 緩存最近使用的方法列表俐填,用于提升效率
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE; // 存儲該類聲明遵守的協(xié)議
#endif

} OBJC2_UNAVAILABLE;

一個(gè)類包含了自身所有的成員變量(ivars)安接、所有的方法(methodLists)、實(shí)現(xiàn)的協(xié)議(protocols

isa的定義如下:

struct objc_object {
    // 是一個(gè)指向objc_class結(jié)構(gòu)體的指針
    // objc_object(實(shí)例對象)中isa指針指向的類結(jié)構(gòu)稱為class(也就是該對象所屬的類)其中存放著普通成員變量與動(dòng)態(tài)方法(“-”開頭的方法)
    Class isa  OBJC_ISA_AVAILABILITY;
};

一個(gè)對象唯一保存的信息就是它的Class的地址

調(diào)用對象方法的實(shí)現(xiàn)過程

  1. 通過isa去找到對應(yīng)的objc_class;
  2. objc_classmethodLists中找到我們調(diào)用的方法英融,然后執(zhí)行盏檐。

Meta Class 元類

Objective-C中,類也被設(shè)計(jì)為一個(gè)對象驶悟。

調(diào)用對象類方法的實(shí)現(xiàn)過程(不考慮繼承)

  1. 通過對象的isa指針找到對應(yīng)的類胡野;
  2. 通過類的isa指針找到對應(yīng)元類;
  3. 在元類的methodList中痕鳍,找到對應(yīng)的方法硫豆,然后執(zhí)行。
所有的metaclass中isa指針都是指向根metaclass笼呆,而根metaclass則指向自身熊响。根metaclass是通過繼承根類產(chǎn)生的,與根class結(jié)構(gòu)體成員一致诗赌,不同的是根metaclass的isa指針指向自身汗茄。

Method

定義如下:

struct objc_method {
    SEL method_name                                          OBJC2_UNAVAILABLE; // 方法名
    char *method_types                                       OBJC2_UNAVAILABLE; // 方法類型
    IMP method_imp                                           OBJC2_UNAVAILABLE; // 方法實(shí)現(xiàn)
}

SEL是一個(gè)指向objc_selector的指針,而非objc_selector在頭文件中找不到明確的定義铭若。不過是一個(gè)保存方法名的字符串洪碳。

IMP函數(shù)指針:找到函數(shù)地址递览,然后執(zhí)行函數(shù)。

typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...)

id對于實(shí)例方法來說瞳腌,self保存了當(dāng)前對象的地址绞铃;對于類方法來說,self保存了當(dāng)前對應(yīng)類對象的地址嫂侍;后面的省略號即是參數(shù)列表儿捧。

Method建立了SELIMP的關(guān)聯(lián),當(dāng)對一個(gè)對象發(fā)送消息時(shí)吵冒,會通過給出的SEL去找到IMP纯命,然后執(zhí)行。

objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)

當(dāng)向一個(gè)對象發(fā)送消息時(shí)痹栖,會去這個(gè)類methodLists中查找對應(yīng)的SEL亿汞,如果查不到,則通過super_class指針找到父類揪阿,再去父類的methodLists中查找疗我,層層遞進(jìn)。最后仍然找不到南捂,才走拋異常流程吴裤。

攔截調(diào)用和消息轉(zhuǎn)發(fā)流程
重寫

resolveClassMethod:
resolveInstanceMethod:

消息發(fā)送

基本的消息發(fā)送框架

objc_msgSend函數(shù)的調(diào)用過程:

  • 第一步:檢測這個(gè)selector是不是要忽略的。
  • 第二步:檢測這個(gè)target是不是nil對象溺健。nil對象發(fā)送任何一個(gè)消息都會被忽略掉麦牺。
  • 第三步:
    1.調(diào)用實(shí)例方法時(shí),它會首先在自身isa指針指向的類(classmethodLists中查找該方法鞭缭,如果找不到則會通過classsuper_class指針找到父類的類對象結(jié)構(gòu)體剖膳,然后從methodLists中查找該方法,如果仍然找不到岭辣,則繼續(xù)通過super_class向上一級父類結(jié)構(gòu)體中查找吱晒,直至根class
    2.當(dāng)我們調(diào)用某個(gè)某個(gè)類方法時(shí)沦童,它會首先通過自己的isa指針找到metaclass仑濒,并從其中methodLists中查找該類方法,如果找不到則會通過metaclasssuper_class指針找到父類的metaclass對象結(jié)構(gòu)體偷遗,然后從methodLists中查找該方法墩瞳,如果仍然找不到,則繼續(xù)通過super_class向上一級父類結(jié)構(gòu)體中查找氏豌,直至根metaclass矗烛;
  • 第四部:前三部都找不到就會進(jìn)入動(dòng)態(tài)方法解析(看下文)。
動(dòng)態(tài)方法解析
  • 第一步:通過resolveInstanceMethod:方法決定是否動(dòng)態(tài)添加方法箩溃。如果返回Yes則通過class_addMethod動(dòng)態(tài)添加方法瞭吃,消息得到處理,結(jié)束涣旨;如果返回NO歪架,則進(jìn)入下一步;

  • 第二步:這步會進(jìn)入forwardingTargetForSelector:方法霹陡,用于指定備選對象響應(yīng)這個(gè)selector和蚪,不能指定為self。如果返回某個(gè)對象則會調(diào)用對象的方法烹棉,結(jié)束攒霹。如果返回nil,則進(jìn)入第三部浆洗;

  • 第三部:這步我們要通過methodSignatureForSelector:方法簽名催束,如果返回nil,則消息無法處理伏社。如果返回methodSignature`抠刺,則進(jìn)入下一步;

  • 第四部:這步調(diào)用forwardInvocation:方法摘昌,我們可以通過 anInvocation對象做很多處理速妖,比如修改實(shí)現(xiàn)方法,修改響應(yīng)對象等聪黎,如果方法調(diào)用成功罕容,則結(jié)束。如果失敗稿饰,則進(jìn)入doesNotRecognizeSelector方法锦秒,若我們沒有實(shí)現(xiàn)這個(gè)方法,那么就會crash湘纵。

Category

struct objc_category {
    char *category_name                                      OBJC2_UNAVAILABLE; // 類別名稱
    char *class_name                                         OBJC2_UNAVAILABLE; // 類名
    struct objc_method_list *instance_methods                OBJC2_UNAVAILABLE; // 實(shí)例方法列表
    struct objc_method_list *class_methods                   OBJC2_UNAVAILABLE; // 類方法列表
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE; // 協(xié)議列表
}       

objc_category中包含對象方法列表脂崔、類方法列表、協(xié)議列表梧喷。

可以通過關(guān)聯(lián)對象的方式給類別添加可用的屬性

Runtime的常規(guī)操作

  1. Method Swizzling方法交換
  2. 獲取所有屬性和方法

Runtime的應(yīng)用場景

  1. AOP面向切面編程(對業(yè)務(wù)邏輯進(jìn)行分離砌左,降低耦合度)
  2. 字典轉(zhuǎn)模型
  3. 進(jìn)行歸解檔
  4. 逆向開發(fā)
  5. 熱修復(fù)

新手也看得懂的 iOS Runtime 教程
RSSwizzle源碼解析
Objective-C Runtime 1小時(shí)入門教程
深入理解Objective-C:Category

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铺敌,隨后出現(xiàn)的幾起案子汇歹,更是在濱河造成了極大的恐慌,老刑警劉巖偿凭,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件产弹,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)痰哨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門胶果,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斤斧,你說我怎么就攤上這事早抠。” “怎么了撬讽?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵蕊连,是天一觀的道長。 經(jīng)常有香客問我游昼,道長甘苍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任烘豌,我火速辦了婚禮载庭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扇谣。我一直安慰自己昧捷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布罐寨。 她就那樣靜靜地躺著靡挥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸯绿。 梳的紋絲不亂的頭發(fā)上跋破,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機(jī)與錄音瓶蝴,去河邊找鬼毒返。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舷手,可吹牛的內(nèi)容都是我干的拧簸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼男窟,長吁一口氣:“原來是場噩夢啊……” “哼盆赤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起歉眷,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤牺六,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后汗捡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淑际,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了春缕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盗胀。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖淡溯,靈堂內(nèi)的尸體忽然破棺而出读整,到底是詐尸還是另有隱情,我是刑警寧澤咱娶,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站强品,受9級特大地震影響膘侮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜的榛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一琼了、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧夫晌,春花似錦雕薪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凶掰,卻和暖如春燥爷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背懦窘。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工前翎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畅涂。 一個(gè)月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓港华,卻偏偏與公主長得像,于是被迫代替她去往敵國和親午衰。 傳聞我的和親對象是個(gè)殘疾皇子立宜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,721評論 0 9
  • 我們常常會聽說 Objective-C 是一門動(dòng)態(tài)語言苇经,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢赘理?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,195評論 0 7
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 735評論 0 2
  • Objective-C語言是一門動(dòng)態(tài)語言,他將很多靜態(tài)語言在編譯和鏈接時(shí)期做的事情放到了運(yùn)行時(shí)來處理扇单。這種動(dòng)態(tài)語言...
    tigger丨閱讀 1,404評論 0 8
  • 2018年3月31號商模,晉城市心理學(xué)會第二小組第二次成長團(tuán)體課如期舉行。本次主持人是張海燕老師∈┝鳎活動(dòng)中响疚,張老...
    rainbow琴閱讀 91評論 0 0