最近在研究Runtime漓糙,因此铣缠,打算寫一篇文章跟小伙伴兒們分享一下。好了兼蜈,廢話不多說攘残,直接上干貨拙友。
RunTime簡稱運行時为狸。OC就是運行時機制,也就是在運行時候的一些機制遗契,其中最主要的是消息機制辐棒。簡單說一下C與OC在編譯和運行階段的區(qū)別,對于C語言牍蜂,函數的調用在編譯的時候會決定調用哪個函數漾根。對于OC的函數,屬于動態(tài)調用過程鲫竞,在編譯的時候并不能決定真正調用哪個函數辐怕,只有在真正運行的時候才會根據函數的名稱找到對應的函數來調用。
Runtime有5大作用:發(fā)送消息从绘,交換方法寄疏,動態(tài)添加方法,給分類添加屬性僵井,字典轉模型陕截,下面一一給大家講解一下這5個作用。
一批什、發(fā)送消息
任何方法調用的本質就是發(fā)送一個消息农曲,用runtime發(fā)送消息,OC底層就是通過runtime實現的驻债。下面給大家展示一下底層的代碼:
正常的OC代碼通過Xcode的編譯器Clang重新編譯乳规,就會生成底層的代碼,也就是消息機制的代碼合呐。話說回來暮的,怎么使用編譯器重新編譯呢?我們在終端輸入clang -rewrite-objc main.m 就可以得到最終生成代碼了合砂。
我們使用Runtime時青扔,必須要提前導入頭文件<objc/message.h>源织,可能有人會問我,為什么不導入<objc/runtime.h>?因為我們進入message.h的聲明中微猖,會發(fā)現已經導入了runtime.h谈息。
上面展示的代碼是最底層的代碼,寫著太麻煩了凛剥,很少用侠仇,下面給大家展示一下我們平常寫的代碼:
這個就是我們平常寫的,第一個參數的意思是:誰發(fā)送消息?????? 第二個參數的意思是:發(fā)送什么消息犁珠。
其實逻炊,還有一種寫法,也是可以的:
上面僅僅給大家展示了一些消息機制底層代碼的一下寫法犁享,下面說一下Runtime在消息機制中最重要的一個作用:“runtime消息機制,可以調用私有方法”S嗨亍!4独ァ=暗酢!凤巨!
下面給大家展示一下视乐,調用私有方法:
上面的eat,run方法在Person類中均沒有聲明敢茁,只有實現佑淀。
注:我們在用對象p調用方法時,不要用Person *p = objc_msgSend(object_getClass(@"Person"), sel_registerName("alloc"))這種形式彰檬,否則伸刃,會崩。
上面是對象方法僧叉,下面給大家展示一下類方法奕枝。
對象方法的對象調用,類方法的本質是類對象調用瓶堕。
下面隘道,給大家分享一下方法的調用流程:
1.去尋找對應的類對象,每一個對象都有一個isa指針郎笆,通過isa指針去對應類中查找谭梗;
2.注冊方法編號
3.根據方法編號查找對應的方法
4.找到只是最終函數實現地址,根據地址去方法區(qū)調用對應函數。
二宛蚓、交換方法
交換方法是Runtime中最常用的激捏,我們在做項目時經常用到。
Runtime(交換方法):只要想修改系統(tǒng)的方法實現凄吏。
比如:有一個項目,已經開發(fā)了2年,忽然項目負責人添加一個功能,每次UIImage加載圖片,告訴我是否加載成功远舅?
這樣的一個需求闰蛔,除了使用Runtime交換方法,用其他的方法很難實現图柏。
交換方法的步驟為:(1)給系統(tǒng)的方法添加分類;
??????????????????????????????? (2)自己實現一個帶有擴展功能的方法;
??????????????????????????????? (3)交換方法的實現序六,只需要交換一次。
下面直接上代碼:
分類的聲明:
分類的實現:
三蚤吹、動態(tài)添加方法
動態(tài)添加方法:OC是懶加載機制,只要一個方法實現了,就會馬上添加到方法列表中(不管這個方法有沒有用過例诀,都會添加進去)。如果某個類中方法比較多裁着,而且有很多方法不常用繁涂,需要給每個方法都生成映射表,加載類到內存的時候就比較耗費資源二驰,可以使用動態(tài)給該類添加方法解決扔罪。
下面直接上代碼:
Person類的實現部分:
動態(tài)添加方法在做項目時用得比較少。
4诸蚕、動態(tài)添加屬性
我們給系統(tǒng)的類添加屬性的時候步势,可以使用runtime動態(tài)添加屬性。動態(tài)添加屬性的本質:讓某個屬性和某個對象產生一個關聯背犯,并不是直接把這個值的內存空間添加到類內存空間。
代碼如下:
給系統(tǒng)的類添加一個分類盅抚,聲明部分:
實現部分:
4漠魏、字典轉模型
字典轉模型有兩種方法:1.KVC? 2.Runtime。第三方框架MJExtension底層就是用Runtime字典轉模型的妄均。
KVC的實現原理是:遍歷字典中所有的key柱锹,去模型中查找對應的屬性賦值;Runtime實現原理剛好與KVC相反:通過runtime丰包,把一個模型中所有屬性遍歷出來禁熏,根據屬性去字典里面找。
我們可以創(chuàng)建一個NSObject分類邑彪,專門字典轉模型瞧毙,以后所有模型都可以通過這個分類轉
代碼如下: