本系列主要參考資料:
Objective-C Runtime Reference
Objective-C Runtime Programming Guide
涉及主要文件:objc/message.h,objc/objc-api.h,objc/objc.h,objc/runtime.h

特酷吧[tekuba.net]採用"署名-非商業用途-保持一致"的創做共用協議,使用本文內容請遵循該協議
Objective-C Runtime是Objective-C的基礎內容,理解了Objective-C Runtime對於掌握Objective-C的不少技術原理很是有用。特酷吧特別整理了Objective-C Runtime的內容,共六篇,本文是第二篇:
Objective-C Runtime分析(一)-Runtime初步
Objective-C Runtime分析(二)-Class,Method,SEL,IMP
Objective-C Runtime分析(三)-objc_msgSend
Objective-C Runtime分析(四)--Dynamic Method Resolution
Objective-C Runtime分析(五)-Message Forwarding
Objective-C Runtime分析(六)-Type Encodings & Declared Properties

本文參考地址:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html
本文主要分析了與Objective-C Runtime密切相關的幾個數據類型/概念:Class , Method,,SEL , IMP ,他們都在objc/objc.h中定義。先來看看他們的定義。
javascript

摺疊 C/C++ Code 複製內容到剪貼板
  1. typedef struct objc_class *Class;  
  2. typedef struct objc_object {  
  3.     Class isa;  
  4. } *id;//能夠看到,iOS中很重要的id實際上就是objc_object的指針.而NSObject的第一個對象就是Class類型的isa。所以id能夠標示全部基於NSObject的對象。  
  5. typedef struct objc_selector     *SEL;  
  6. #if !OBJC_OLD_DISPATCH_PROTOTYPES  
  7. typedef void (*IMP)(void /* id, SEL, ... */ );  
  8. #else  
  9. typedef id (*IMP)(id, SEL, ...);  
  10. #endif  


一,Class
Class 被定義爲一個指向objc_class的結構體指針,表示一個類的類結構。objc_class在objc/objc_class.h中定義以下:
html

摺疊 C/C++ Code 複製內容到剪貼板
  1. struct objc_class {  
  2.     Class isa;  
  3.   
  4. #if !__OBJC2__  
  5.     Class super_class                                        OBJC2_UNAVAILABLE;/*父類*/  
  6.     const char *name                                         OBJC2_UNAVAILABLE;/*類名稱*/  
  7.     long version                                             OBJC2_UNAVAILABLE;/*版本信息*/  
  8.     long info                                                OBJC2_UNAVAILABLE;/*類信息*/  
  9.     long instance_size                                       OBJC2_UNAVAILABLE;/*實例大小*/  
  10.     struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;/*實例參數鏈表*/  
  11.     struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;/*類方法鏈表*/  
  12.     struct objc_cache *cache                                 OBJC2_UNAVAILABLE;/*類方法緩存*/  
  13.     struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;/*協議鏈表*/  
  14. #endif  
  15. } OBJC2_UNAVAILABLE;  


可見,Class是指向類結構體的指針,該類結構體含有一個指向其父類類結構的指針,該類方法的鏈表,該類方法的緩存以及其餘信息。
NSObject 的class方法就返回這樣一個指向其類結構的指針。每個基於NSObject的類實例對象都有一個指向該對象的類結構的指針,叫作isa。經過該指針,對象能夠訪問它對應的類以及相應的父類。

二,Method
Method是Runtime內部定義的方法,Class中定義有一個objc_method_list,鏈表都是objc_method類型的,定義以下:
java

摺疊 C/C++ Code 複製內容到剪貼板
  1. typedef struct objc_method *Method;  
  2. struct objc_method {  
  3.     SEL method_name                                          OBJC2_UNAVAILABLE;/*標示方法名稱*/  
  4.     char *method_types                                       OBJC2_UNAVAILABLE;/*方法的參數類型*/  
  5.     IMP method_imp                                           OBJC2_UNAVAILABLE;/*指向該方法的具體實現的函數指針*/  
  6. }  
  7.       
  8. struct objc_method_list {  
  9.     struct objc_method_list *obsolete                        OBJC2_UNAVAILABLE;  
  10.   
  11.     int method_count                                         OBJC2_UNAVAILABLE;  
  12. #ifdef __LP64__  
  13.     int space                                                OBJC2_UNAVAILABLE;  
  14. #endif  
  15.     /* variable length structure */  
  16.     struct objc_method method_list[1]                        OBJC2_UNAVAILABLE;  
  17. }  


三,SEL
定義以下:
typedef struct objc_selector     *SEL;
標示該方法的名字/簽名
示例:
-(void)helloTekuba:(NSString *)url port:(int)port
{
    NSLog(@"%@,%d",url,port);
}

NSLog(@"SEL = %s",@selector(helloTekuba:port:));
打印結果:
SEL = helloTekuba:port:
不一樣的類能夠擁有相同的selector,不一樣類的實例對象performSelector相同的selector時,會在各自的方法鏈表中根據 selector 去查找具體的方法實現IMP, 而後用這個方法實現去執行具體的實現代碼。這是一個動態綁定的過程,在編譯的時候,咱們不知道最終會執行哪一些代碼,只有在執行的時候,經過selector去查詢,咱們才能肯定具體的執行代碼。

四,IMP
typedef id (*IMP)(id, SEL, ...);
咱們知道 id是一個指向 objc_object 結構體的指針(請看本文前面objc_object的定義),該結構體只有一個成員isa,因此任何繼承自 NSObject 的類對象均可以用id 來指代,由於 NSObject 的第一個成員實例就是isa。
IMP 是一個函數指針,這個被指向的函數包含一個接收消息的對象id, 調用方法的選標 SEL,以及不定個數的方法參數,並返回一個id。也就是說IMP是消息最終調用的執行代碼,是方法真正的實現代碼 。咱們能夠像在C語言裏面同樣使用這個函數指針。
NSObject 類中的methodForSelector:方法就是這樣一個獲取指向方法實現IMP 的指針,methodForSelector:返回的指針和賦值的變量類型必須徹底一致,包括方法參數類型和返回值類型。

五,其餘
Ivar
Runtime中用來表示instance variable,實例變量,跟某個對象關聯,不能被靜態方法使用,與之想對應的是class variable,其聲明以下:
typedef struct objc_ivar *Ivar;

Category
Runtime中用來表示Category,其聲明爲:
typedef struct objc_category *Category;
Catagory能夠動態地爲已經存在的類添加新的行爲。這樣能夠保證類的原始設計規模較小,功能增長時再逐步擴展。使用Category對類進行擴展時,不須要訪問其源代碼,也不須要建立子類。關於更多Catagory的知識能夠參考:http://www.tekuba.net/program/312/
轉載請註明來自特酷吧,本文地址:www.tekuba.net/program/336/
推薦閱讀:
XCode lipo命令使用的一點知識
UINavigationController彈出(pop)和壓入(push)操做的一個問題
IOS後臺運行淺析
IOS7 Background Fetch後臺應用程序刷新
IOS NSProcessInfo獲取系統開機累計時間
node

想及時獲取特酷吧的更新?想了解iOS,android開發最新技術動態,點擊或掃描下方二維碼下載「多識閱讀」App,豐富的iOS,Android,Web等領域開發者博客隨你訂閱。android

多識閱讀