本文為L(zhǎng)_Ares個(gè)人寫(xiě)作,以任何形式轉(zhuǎn)載請(qǐng)表明原文出處。
這個(gè)Runtime我相信做iOS開(kāi)發(fā)的各位小伙伴簡(jiǎn)直太熟悉了。全都知道它是運(yùn)行時(shí)吧。我寫(xiě)這篇的主要目的就是回顧復(fù)習(xí)一下這個(gè)iOS開(kāi)發(fā)中的重中之重Runtime,如果有錯(cuò)誤的地方,還請(qǐng)各位小伙伴幫忙指出,感激不盡。
一、什么是Runtime
聊到Runtime就不得不提一下C和C++這兩位大哥,在C和C++中,程序從代碼變成一個(gè)可執(zhí)行的程序,通常都要經(jīng)歷5個(gè)步驟 :
預(yù)處理--->編譯--->匯編--->鏈接--->可執(zhí)行文件
而在鏈接的時(shí)候,對(duì)象的類型和方法的實(shí)現(xiàn)就已經(jīng)確定好了,這時(shí)候你已經(jīng)無(wú)法動(dòng)態(tài)的去修改它們了。
但是,為了讓OC變得靈活,蘋(píng)果在底層利用C、C++、匯編混合開(kāi)發(fā)了一套api,這套api為OC提供了運(yùn)行時(shí)可以動(dòng)態(tài)修改一些方法的功能,這套api就是Runtime。由于有了這套Runtime,OC就變成了一門(mén)運(yùn)行時(shí)語(yǔ)言。
總結(jié)一句更簡(jiǎn)單的話說(shuō)Runtime :
Runtime就是一套由C、C++、匯編混編的庫(kù),這個(gè)庫(kù)提供了api,在程序運(yùn)行的時(shí)候可以動(dòng)態(tài)的對(duì)方法和對(duì)象做一些操作。
二、關(guān)于運(yùn)行時(shí)
說(shuō)到運(yùn)行時(shí),這個(gè)其實(shí)應(yīng)該是程序員的一個(gè)必備素質(zhì),運(yùn)行時(shí)說(shuō)的再明白一點(diǎn),就是可執(zhí)行文件的加載。
這個(gè)是不是就無(wú)比的熟悉了?
其實(shí)就是C語(yǔ)言的代碼變成輸出的流程吧??匆幌?,里面運(yùn)行時(shí)和編譯將是重點(diǎn)比對(duì),畢竟Runtime這個(gè)庫(kù)最重要的功能還是給OC提供運(yùn)行時(shí)的靈活操作。
預(yù)處理(Preprocessing): 也有人叫它預(yù)編譯,主要處理的就是#開(kāi)頭的東西,比如#include啊,比如#define啊,這之類的。就是把這些東西定義的東西插入到它們?cè)摬迦氲牡胤健?/p>編譯(Compilation): 把高級(jí)語(yǔ)言(比如C、C++等等就不舉例了)變成匯編語(yǔ)言,啥是匯編語(yǔ)言?說(shuō)白了就是機(jī)器指令,就是一大段英文字母的文字,這段文字都是命令,發(fā)給計(jì)算機(jī)的命令。在這個(gè)階段,會(huì)對(duì)你給計(jì)算機(jī)發(fā)的命令進(jìn)行查錯(cuò),比如語(yǔ)法分析啊、詞法分析啊之類的。這個(gè)階段是靜態(tài)的。匯編(Assembly): 就是把你上面編譯的機(jī)器指令全變成0和1。這回就不是人類能輕易看懂的東西了。鏈接(Linking): 你的代碼可能會(huì)用到很多的第三方庫(kù)吧,就是把你的代碼和庫(kù)揉搓成一個(gè)可執(zhí)行的文件。
這里重點(diǎn)來(lái)了,就是運(yùn)行時(shí)
-
加載(Loading): 這就是運(yùn)行時(shí),就是把你鏈接完成的可執(zhí)行文件從磁盤(pán)放到內(nèi)存里面。然后計(jì)算機(jī)就對(duì)著你的可執(zhí)行文件瘋狂輸出,這個(gè)過(guò)程被runtime搞成了動(dòng)態(tài)的,就是在你的代碼輸出之前,runtime可以改了它。這就是所謂的運(yùn)行時(shí)。
三、Runtime怎么用
大體的看,常用的方式就3種。
通過(guò)
OC代碼,這里就是我們要探索Runtime的最直接的入口了,畢竟我們寫(xiě)的大多還是OC。怎么通過(guò)OC代碼?其實(shí)不是我們通過(guò)OC代碼,而是編譯的時(shí)候,OC的方法會(huì)變成objc_msgSend,例如 :[person run];。通過(guò)
NSObject,這個(gè)怎么理解呢?這個(gè)其實(shí)最好理解,因?yàn)樵?code>OC中,萬(wàn)物皆NSObject??梢渣c(diǎn)到NSObject.h去看一下。例如 :isKindOfClass。通過(guò)
Runtime的API,這就是更直白的了,直接上手用Runtime了。例如 :object_getClass。
下面放一張圖來(lái)理解一下,通過(guò)3種方式是如何可以使用Runtime的。

Runtime System Library的方法和最上面的三個(gè)是映射關(guān)系,通過(guò)編譯(Complier)完成的映射。
這里我就不再多加內(nèi)容了,因?yàn)閷?duì)Runtime的介紹實(shí)際就這么多,畢竟這是一套api,本節(jié)不對(duì)Runtime的api做多的解釋,主要就是說(shuō)明這個(gè)庫(kù)的一些常識(shí)。下節(jié)開(kāi)始進(jìn)入Runtime的探索。