最近在研究Runtime,因此,打算寫一篇文章跟小伙伴兒們分享一下。好了,廢話不多說,直接上干貨。
RunTime簡稱運行時。OC就是運行時機制,也就是在運行時候的一些機制,其中最主要的是消息機制。簡單說一下C與OC在編譯和運行階段的區(qū)別,對于C語言,函數(shù)的調用在編譯的時候會決定調用哪個函數(shù)。對于OC的函數(shù),屬于動態(tài)調用過程,在編譯的時候并不能決定真正調用哪個函數(shù),只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應的函數(shù)來調用。
Runtime有5大作用:發(fā)送消息,交換方法,動態(tài)添加方法,給分類添加屬性,字典轉模型,下面一一給大家講解一下這5個作用。
一、發(fā)送消息
任何方法調用的本質就是發(fā)送一個消息,用runtime發(fā)送消息,OC底層就是通過runtime實現(xiàn)的。下面給大家展示一下底層的代碼:

正常的OC代碼通過Xcode的編譯器Clang重新編譯,就會生成底層的代碼,也就是消息機制的代碼。話說回來,怎么使用編譯器重新編譯呢?我們在終端輸入clang -rewrite-objc main.m 就可以得到最終生成代碼了。
我們使用Runtime時,必須要提前導入頭文件<objc/message.h>,可能有人會問我,為什么不導入<objc/runtime.h>?因為我們進入message.h的聲明中,會發(fā)現(xiàn)已經導入了runtime.h。
上面展示的代碼是最底層的代碼,寫著太麻煩了,很少用,下面給大家展示一下我們平常寫的代碼:

這個就是我們平常寫的,第一個參數(shù)的意思是:誰發(fā)送消息?????? 第二個參數(shù)的意思是:發(fā)送什么消息。
其實,還有一種寫法,也是可以的:

上面僅僅給大家展示了一些消息機制底層代碼的一下寫法,下面說一下Runtime在消息機制中最重要的一個作用:“runtime消息機制,可以調用私有方法”?。。。。?!
下面給大家展示一下,調用私有方法:

上面的eat,run方法在Person類中均沒有聲明,只有實現(xiàn)。
注:我們在用對象p調用方法時,不要用Person *p = objc_msgSend(object_getClass(@"Person"), sel_registerName("alloc"))這種形式,否則,會崩。
上面是對象方法,下面給大家展示一下類方法。
對象方法的對象調用,類方法的本質是類對象調用。

下面,給大家分享一下方法的調用流程:
1.去尋找對應的類對象,每一個對象都有一個isa指針,通過isa指針去對應類中查找;
2.注冊方法編號
3.根據(jù)方法編號查找對應的方法
4.找到只是最終函數(shù)實現(xiàn)地址,根據(jù)地址去方法區(qū)調用對應函數(shù)。
二、交換方法
交換方法是Runtime中最常用的,我們在做項目時經常用到。
Runtime(交換方法):只要想修改系統(tǒng)的方法實現(xiàn)。
比如:有一個項目,已經開發(fā)了2年,忽然項目負責人添加一個功能,每次UIImage加載圖片,告訴我是否加載成功?
這樣的一個需求,除了使用Runtime交換方法,用其他的方法很難實現(xiàn)。
交換方法的步驟為:(1)給系統(tǒng)的方法添加分類;
??????????????????????????????? (2)自己實現(xiàn)一個帶有擴展功能的方法;
??????????????????????????????? (3)交換方法的實現(xiàn),只需要交換一次。
下面直接上代碼:
分類的聲明:

分類的實現(xiàn):


三、動態(tài)添加方法
動態(tài)添加方法:OC是懶加載機制,只要一個方法實現(xiàn)了,就會馬上添加到方法列表中(不管這個方法有沒有用過,都會添加進去)。如果某個類中方法比較多,而且有很多方法不常用,需要給每個方法都生成映射表,加載類到內存的時候就比較耗費資源,可以使用動態(tài)給該類添加方法解決。
下面直接上代碼:
Person類的實現(xiàn)部分:



動態(tài)添加方法在做項目時用得比較少。
4、動態(tài)添加屬性
我們給系統(tǒng)的類添加屬性的時候,可以使用runtime動態(tài)添加屬性。動態(tài)添加屬性的本質:讓某個屬性和某個對象產生一個關聯(lián),并不是直接把這個值的內存空間添加到類內存空間。
代碼如下:

給系統(tǒng)的類添加一個分類,聲明部分:

實現(xiàn)部分:

4、字典轉模型
字典轉模型有兩種方法:1.KVC? 2.Runtime。第三方框架MJExtension底層就是用Runtime字典轉模型的。
KVC的實現(xiàn)原理是:遍歷字典中所有的key,去模型中查找對應的屬性賦值;Runtime實現(xiàn)原理剛好與KVC相反:通過runtime,把一個模型中所有屬性遍歷出來,根據(jù)屬性去字典里面找。
我們可以創(chuàng)建一個NSObject分類,專門字典轉模型,以后所有模型都可以通過這個分類轉
代碼如下:
