Runtime簡介
對于C語言,函數(shù)的調(diào)用在編譯的時候會決定調(diào)用哪個函數(shù),如果調(diào)用未實現(xiàn)的函數(shù)就會報錯。對于OC語言,屬于動態(tài)調(diào)用過程,在編譯的時候并不能決定真正調(diào)用哪個函數(shù),只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應(yīng)的函數(shù)來調(diào)用。在編譯階段,OC可以調(diào)用任何函數(shù),即使這個函數(shù)并未實現(xiàn),只要聲明過就不會報錯。
Object-c運行時版本
在現(xiàn)行版本中,最顯著的新特性就是實例變量是"健壯“(non-fragile)的:
- 在早期版本中,如果您改變類中實例變量的布局,您必須重新編譯該類的所有子類。
- 在現(xiàn)行版本中,如果您改變類中實例變量的布局,您無需重新編譯該類的任何子類。
- 此外,現(xiàn)行版本支持聲明property的synthesis屬性
平臺
- iPhone 程序和 Mac OS X v10.5 及以后的系統(tǒng)中的 64 位程序使用的都是 - Objective-C 運行時系統(tǒng)的現(xiàn)行版 本。
- 其它情況(Mac OS X 系統(tǒng)中的 32 位程序)使用的是早期版本。
和運行時交互
和運行時交互主要有種方式:
- 大部分情況下runtime在后臺運行,我們只需編寫oc代碼就可以
-
通過 Foundation 框架中類 NSObject 的方法
一些主要方法.png - 通過直接調(diào)用運行時系統(tǒng)的函數(shù)(Runtime API)
消息機制
OC方法調(diào)用實際是objc_msgSend函數(shù)調(diào)用,本質(zhì)是消息機制:消息接收體(類),消息名稱(方法),還可帶參數(shù)。
如果想看是函數(shù)是如何調(diào)用的,可以用下指令會生成對應(yīng)的.cpp 文件,里面就能找到OC方法對應(yīng)的C方法
clang -rewrite-objc xxxx.m
oobjc_msgSend執(zhí)行過程大致可以分為三個過程:
小插曲:
SEL : 類成員方法的指針,但不同于C語言中的函數(shù)指針,函數(shù)指針直接保存了方法的地址,但SEL只是方法編號。
IMP:一個函數(shù)指針,保存了方法的地址
方法編號SEL最后還是要通過Dispatch table表尋找到對應(yīng)的IMP,IMP就是一個函數(shù)指針,然后執(zhí)行這個方法
- 消息發(fā)送
1、消息接收者(Class)判斷消息(func)是否為空,如果為nil就return
2、如果不為空通過isa指針找到類,從類里面緩存里面去找imp,
3、如果找到了,直接返回直接執(zhí)行,如果沒有找到就從類的方法列表去找
4、如果找到了就把方法填充到緩存里面然后把imp進行返回。
5、如果沒有找到嘗試從父類緩存和方法列表里面去找,就一直循環(huán)遍歷到根類(方法執(zhí)行一次之后緩存里面就有了)
動態(tài)方法解析
有時候,您需要動態(tài)地提供一個方法的實現(xiàn)。您可以通過實現(xiàn)resolveInstanceMethod:和resolveClassMethod:來動態(tài)地實現(xiàn)給定選標 的對象方法或者類方法。消息轉(zhuǎn)發(fā)
