iOS底層原理 - isa和superclass

問題:對象的isa指針指向哪裏?

一.isa指針

instance的isa指針指向class。
當調用對象方法時,經過instance的isa指針找到class,最後找到對象方法的實現進行調用。緩存

class的isa指針指向meta-class。
當調用類方法時,經過class的isa指針找到meta-class,最後找到類方法的實現進行調用。ui


二.class的superclass

2.1 class對象的superclass指針

當Student的instance對象要調用Person的對象方法時,會先經過isa找到Student的class,而後經過superclass找到Person的class,最後找到對象方法的實現進行調用。spa

2.2 meta-class對象的superclass指針

當Student的class要調用Person的類方法時,會先經過isa指針找到Student的meta-class,而後經過superclass找到Person的meta-class,最後找到類方法的實現進行調用3d


三.isa細節

從64bit開始,isa須要進行一次位運算,才能計算出真實地址指針

從源碼中能夠查到ISA_MASK的相關信息code


isa、superclass總結

  • 實例對象(instance)的isa指向class
  • 類對象(class)的isa指向meta-class
  • 元類對象(meta-class)的isa指向基類的meta-class
  • 類對象(class)的superclass指向父類的class
    • 若是沒有父類,superclass指針爲nil
  • 元類對象(meta-class)的superclass指向父類的meta-class
    • 基類的meta-class的superclass指向基類的class
  • instance調用對象方法的軌跡
    • isa找到class,方法不存在,就經過superclass找父類
  • class調用類方法的軌跡
    • isa找到meta-class,方法不存在,就經過superclass找父類

四.class和meta-class的結構

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
複製代碼

在runtime.h頭文件中咱們能夠看到一個條件編譯若是不是objc2的版本下,那麼條件範圍內的代碼將不會被執行,因此在OC2.0中,這段代碼已通過時了。並且經過OBJC2_UNAVAILABLE也能夠看出,struct objc_class這個結構體在OC2.0中已經不可用了。orm

4.1 窺探struct objc_class的結構

類和元類在內存中的結構,就是struct objc_class這樣一個結構體,這個結構體在objc-runtime-new.h頭文件中能夠找到最新版本的定義。以下圖結構體struct objc_class中部分代碼所示:cdn

struct objc_class : objc_object {
    Class isa;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable-方法緩存
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags-用於獲取具體的類信息
    ...
    ...
    ...
}
複製代碼

注意: 冒號語法是繼承的意思,結構體objc_class繼承自objc_object,這種語法是C++的語法。對象

class_rw_t *data() const {
    return bits.data();
}
複製代碼
class_rw_t* data() const {
    return (class_rw_t *)(bits & FAST_DATA_MASK);
}
複製代碼

下圖爲老版本代碼結構,能夠參考新版本源碼 blog

struct objc_class結構體中包含上面這樣一段代碼,返回值是class_rw_t,是一個可讀寫的表單。

進入class_rw_t頭文件中咱們能夠看到一段public的代碼,返回值是class_rw_ext_t類型。以下圖所示

class_rw_ext_t *ext() const {
    return get_ro_or_rwe().dyn_cast<class_rw_ext_t *>();
}
複製代碼

進入class_rw_ext_t頭文件,咱們能夠看到方法列表、屬性列表、協議列表的相關定義。以下圖所示

struct class_rw_ext_t {
    const class_ro_t *ro;
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    char *demangledName;
    uint32_t version;
};
複製代碼

進入到class_rw_ext_t結構體中class_ro_t類型的頭文件中,咱們能夠看到instanceSize、ivars的定義。下圖爲頭文件中的部分代碼。

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;
    ...
    ...
    ...
複製代碼

總結: OC的類信息存放在哪裏?

  • 對象方法、屬性、成員變量、協議信息,存放在class對象中。
  • 類方法,存放在meta-class對象中。
  • 成員變量的具體值,存放在instance對象。
相關文章
相關標籤/搜索