RunTime簡介:
RunTime簡稱運行時。OC就是運行時機制,也就是運行時候的一些機制,其中最主要的就是消息機制。
對于C語言,函數(shù)的調用在編譯的時候就會決定調用哪個函數(shù),如果調用未實現(xiàn)的函數(shù)就會報錯。對于OC語言,他是一門動態(tài)的語言,因為他在編譯的時候并不能決定真正調用的是哪個函數(shù),只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應的函數(shù)進行調用。在編譯階段,OC可以調用任何函數(shù),即使這個函數(shù)并未實現(xiàn),只要聲明過就不會報錯。
RunTime消息機制
消息機制是運行時里面最重要的機制,OC中任何方法的調用,本質都是發(fā)送消息。
@selector(SEL):
這是一個方法選擇器。主要作用是快速的通過方法名字查找到對應方法的函數(shù)指針,然后調用其函數(shù)也就是IMP。SEL其本身是一個Int類型的地址,地址中存放著方法名字。對于一個類中,每一個方法對應著一個SEL。所以一個類中不能存在兩個名稱相同的方法,即使參數(shù)類型不同也不行,因為SEL是根據(jù)方法名字生成的,相同的方法名稱只能對應一個SEl。
實例方法和類方法的調用過程

實例方法的調用過程:首先會根據(jù)實例對象的isa指針找到他的類對象,在類對象的對象方法列表中去查找是否有對應實現(xiàn),如果有就調用,沒有就依次去類對象的父類中查找,一直找到NSObject還沒有的話會進入消息轉發(fā),如果在消息轉發(fā)流程(其中有三個方法)還是沒有做處理,就會報找不到方法異常。

類方法的調用過程:首先也是會根據(jù)類對象的isa指針找到它的元類,元類中存儲著類方法列表,如果當前元類的類方法列表沒有,再依次去元類的父類中查找對應實現(xiàn),一直找到根元類,還是沒有的話,這個時候與實例方法調用不同的是,如果類對象里面有同名的實例方法,就回去調用同名的實例方法。如果沒有在進入消息轉發(fā),消息轉發(fā)沒做處理的話就會報找不到方法異常。

Runtime的應用:
獲取列表
Method *methods = class_copyMethodList([UITextView class], &count);
for (int i = 0; i < count; i++) {
Method method = methods[i];
SEL selector = method_getName(method);
NSString *name = NSStringFromSelector(selector);
NSLog(@"method_getName:%@",name);
}
unsigned int numIvars;
Ivar *vars = class_copyIvarList([UITextView class], &numIvars);
NSString *key=nil;
for(int i = 0; i < numIvars; i++) {
Ivar thisIvar = vars[i];
key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
NSLog(@"variable_name :%@", key);
}
1.獲取列表(比如獲取類的屬性列表,方法列表,成員變量列表)。比如實際開發(fā)中做歸檔解檔的時候對象的屬性很多的時候就可以用RunTime這個特性很方便的簡化代碼。
2.方法調用:正如上面所講的實例方法調用和類方法調用。
3.攔截調用:攔截調用就是,在找不到調用的方法程序奔潰之前,你有機會通過重寫NSObject的四個方法來處理。
4.動態(tài)添加方法:如果一個類方法非常多,其中可能許多方法暫時用不到。而加載類方法到內存的時候需要給每個方法生成映射表,比較耗費資源,這個時候就可以用Runtime動態(tài)添加方法。動態(tài)給某個類添加方法,相當于懶加載機制,類中許多方法暫時用不到,那么就先不加載,等用的時候再去加載。另外如果找不到對應的方法時就會來到攔截調用,也就是因為找不到方法實現(xiàn),在奔潰之前可以調用的方法。當調用了沒有實現(xiàn)的對象方法時,就會調用+(BOOL)resolveInstanceMethod:(SEL)sel方法當調用了沒有實現(xiàn)的類方法時,就會調用+(BOOL)resolveClassMethod:(SEL)sel方法,我們就可以實現(xiàn)這兩個方法動態(tài)的給實例方法或者類方法添加方法和方法實現(xiàn)。
5.方法交換:當系統(tǒng)自帶的方法功能不夠,需要給系統(tǒng)自帶的方法擴展一些功能,并且保持原有的功能時,可以使用Runtime交換方法實現(xiàn)。這個特性可以用來處理開發(fā)中常見的奔潰(比如字典添加nil值,和數(shù)組越界等導致的奔潰)或者是統(tǒng)一添加埋點,可以很方便的解決這些問題。