ObjectC Class Method SEL IMP

本文參考地址:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.htmlhtml

本文主要分析了與Objective-C Runtime密切相關的幾個數據類型/概念:Class , Method,,SEL , IMP ,他們都在objc/objc.h中定義。先來看看他們的定義。緩存

typedef struct objc_class *Class;  
typedef struct objc_object {  
    Class isa;  
} *id;//能夠看到,iOS中很重要的id實際上就是objc_object的指針.而NSObject的第一個對象就是Class類型的isa。所以id能夠標示全部基於NSObject的對象。  
typedef struct objc_selector     *SEL;  
#if !OBJC_OLD_DISPATCH_PROTOTYPES  
typedef void (*IMP)(void /* id, SEL, ... */ );  
#else  
typedef id (*IMP)(id, SEL, ...);  
#endif

一,Classapp

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

struct objc_class {  
    Class isa;  
  
#if !__OBJC2__  
    Class super_class                                        OBJC2_UNAVAILABLE;/*父類*/  
    const char *name                                         OBJC2_UNAVAILABLE;/*類名稱*/  
    long version                                             OBJC2_UNAVAILABLE;/*版本信息*/  
    long info                                                OBJC2_UNAVAILABLE;/*類信息*/  
    long instance_size                                       OBJC2_UNAVAILABLE;/*實例大小*/  
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;/*實例參數鏈表*/  
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;/*類方法鏈表*/  
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;/*類方法緩存*/  
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;/*協議鏈表*/  
#endif  
} OBJC2_UNAVAILABLE;

可見,Class是指向類結構體的指針,該類結構體含有一個指向其父類類結構的指針,該類方法的鏈表,該類方法的緩存以及其餘信息。函數

NSObject 的class方法就返回這樣一個指向其類結構的指針。每個基於NSObject的類實例對象都有一個指向該對象的類結構的指針,叫作isa。經過該指針,對象能夠訪問它對應的類以及相應的父類。ui

二,Methodurl

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

typedef struct objc_method *Method;  
struct objc_method {  
    SEL method_name                                          OBJC2_UNAVAILABLE;/*標示方法名稱*/  
    char *method_types                                       OBJC2_UNAVAILABLE;/*方法的參數類型*/  
    IMP method_imp                                           OBJC2_UNAVAILABLE;/*指向該方法的具體實現的函數指針*/  
}  
      
struct objc_method_list {  
    struct objc_method_list *obsolete                        OBJC2_UNAVAILABLE;  
  
    int method_count                                         OBJC2_UNAVAILABLE;  
#ifdef __LP64__  
    int space                                                OBJC2_UNAVAILABLE;  
#endif  
    /* variable length structure */  
    struct objc_method method_list[1]                        OBJC2_UNAVAILABLE;  
}

三,SEL.net

定義以下:設計

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/

相關文章
相關標籤/搜索