對于從事 iOS 開發(fā)人員來說,所有的人都會答出「runtime 是運(yùn)行時(shí)」,什么情況下用runtime?,大部分人能說出「給分類動態(tài)添加屬性 || 交換方法」,再問一句「runtime 消息機(jī)制的調(diào)用流程 || 能體現(xiàn)runtime 強(qiáng)大之處的應(yīng)用場景」,到這,能知道答案的寥寥無幾,很少有人會說到“黑魔法”這三個(gè)字,
runtime 是 iOS 編程中比較難的模塊,想要深入學(xué)習(xí) OC,那 runtime 是你必須要熟練掌握的東西,下面是我對 runtime 的整理,從零開始,由淺入深,并且?guī)Я藥讉€(gè) runtime 實(shí)際開發(fā)的應(yīng)用場景。
runtime 概念
Objective-C 是基于 C 的,它為 C 添加了面向?qū)ο蟮奶匦?。它將很多靜態(tài)語言在編譯和鏈接時(shí)期做的事放到了 runtime 運(yùn)行時(shí)來處理,可以說 runtime 是我們 Objective-C 幕后工作者。
runtime(簡稱運(yùn)行時(shí)),是一套 純C(C和匯編寫的) 的API。而 OC 就是 運(yùn)行時(shí)機(jī)制,也就是在運(yùn)行時(shí)候的一些機(jī)制,其中最主要的是 消息機(jī)制。
對于 C 語言,函數(shù)的調(diào)用在編譯的時(shí)候會決定調(diào)用哪個(gè)函數(shù)。
OC的函數(shù)調(diào)用成為消息發(fā)送,屬于 動態(tài)調(diào)用過程。在編譯的時(shí)候并不能決定真正調(diào)用哪個(gè)函數(shù),只有在真正運(yùn)行的時(shí)候才會根據(jù)函數(shù)的名稱找到對應(yīng)的函數(shù)來調(diào)用。
事實(shí)證明:在編譯階段,OC 可以 調(diào)用任何函數(shù),即使這個(gè)函數(shù)并未實(shí)現(xiàn),只要聲明過就不會報(bào)錯(cuò),只有當(dāng)運(yùn)行的時(shí)候才會報(bào)錯(cuò),這是因?yàn)镺C是運(yùn)行時(shí)動態(tài)調(diào)用的。而 C 語言 調(diào)用未實(shí)現(xiàn)的函數(shù) 就會報(bào)錯(cuò)。
runtime 消息機(jī)制
我們寫 OC 代碼,它在運(yùn)行的時(shí)候也是轉(zhuǎn)換成了 runtime 方式運(yùn)行的。任何方法調(diào)用本質(zhì):就是發(fā)送一個(gè)消息(用 runtime發(fā)送消息,OC 底層實(shí)現(xiàn)通過 runtime 實(shí)現(xiàn))。
消息機(jī)制原理:對象根據(jù)方法編號SEL去映射表查找對應(yīng)的方法實(shí)現(xiàn)。
每一個(gè) OC 的方法,底層必然有一個(gè)與之對應(yīng)的 runtime 方法。

簡單示例:
驗(yàn)證:方法調(diào)用,是否真的是轉(zhuǎn)換為消息機(jī)制?
必須要導(dǎo)入頭文件 #import
注解1:我們導(dǎo)入系統(tǒng)的頭文件,一般用尖括號。
注解2:OC 解決消息機(jī)制方法提示步驟【查找build setting -> 搜索msg -> objc_msgSend(YES --> NO)】
注解3:最終生成消息機(jī)制,編譯器做的事情,最終代碼,需要把當(dāng)前代碼重新編譯,用xcode編譯器,【clang -rewrite-objc main.m 查看最終生成代碼】,示例:cd main.m --> 輸入前面指令,就會生成 .opp文件(C++代碼)
注解4:這里一般不會直接導(dǎo)入

#示例代碼:OC 方法-->runtime 方法#