《Objective-C Runtime分析(二)-Class,Method,SEL,IMP》

來源:互聯網
上載者:User

標籤:

 

本系列主要參考資料:
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中定義。先來看看他們的定義。

摺疊展開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中定義如下:

摺疊展開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類型的,定義如下:

摺疊展開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擷取系統開機累計時間

想及時擷取特酷吧的更新?想瞭解iOS,android開發最新技術動態,點擊或掃描下方二維碼下載“多識閱讀”App,豐富的iOS,Android,Web等領域開發人員部落格隨你訂閱。

 

 

 

《Objective-C Runtime分析(二)-Class,Method,SEL,IMP》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.