isa指針

image.png
  • instance的isa指向class
    當(dāng)調(diào)用對象方法時(shí),通過instance的isa找到class,最后找到對象方法的實(shí)現(xiàn)進(jìn)行調(diào)用
  • class的isa指向meta-class
    當(dāng)調(diào)用類方法時(shí),通過class的isa找到meta-class,最后找到類方法的實(shí)現(xiàn)進(jìn)行調(diào)用

class對象的superclass指針

image.png

當(dāng)Student的instance對象要調(diào)用Person的對象方法時(shí),會(huì)先通過isa找到Student的class,然后通過superclass找到Person的class,最后找到對象方法的實(shí)現(xiàn)進(jìn)行調(diào)用

meta-class對象的superclass指針

image.png

當(dāng)Student的class要調(diào)用Person的類方法時(shí),會(huì)先通過isa找到Student的meta-class,然后通過superclass找到Person的meta-class,最后找到類方法的實(shí)現(xiàn)進(jìn)行調(diào)用

isa、superclass總結(jié)

  • 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調(diào)用對象方法的軌跡
    isa找到class,方法不存在,就通過superclass找父類
  • class調(diào)用類方法的軌跡
    isa找meta-class,方法不存在,就通過superclass找父類
image.png

從64bit開始,isa需要進(jìn)行一次位運(yùn)算,才能計(jì)算出真實(shí)地址,如下圖:


image.png
# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
image.png
(lldb) p/x person->isa
(Class) $5 = 0x001d8001000014d1 LQPerson//isa指針的地址
(lldb) p/x 0x001d8001000014d1 & 0x00007ffffffffff8
(long) $6 = 0x00000001000014d0 //class對象的地址

struct objc_class的結(jié)構(gòu)

image.png

源碼中的定義如下:

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;


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

    class_rw_t *data() { 
        return bits.data();
    }
    void setData(class_rw_t *newData) {
        bits.setData(newData);
    }
......

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;

    char *demangledName;

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;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

    method_list_t *baseMethods() const {
        return baseMethodList;
    }
};

ro--readonly
rw--readwrite

struct lq_objc_class {
    Class isa;
    Class superclass;
};

LQPerson *person = [[LQPerson alloc] init];
Class personClass = [LQPerson class];
打印結(jié)果如下:
(lldb) p/x person->isa
(Class) $0 = 0x001d8001000014c9 LQPerson
(lldb) p/x personClass
(Class) $1 = 0x00000001000014c8 LQPerson
(lldb) p/x 0x001d8001000014c9 & 0x0000000ffffffff8
(long) $2 = 0x00000001000014c8

由此可見,實(shí)例對象的的isa確實(shí)指向class對象
也可以通過如下方式驗(yàn)證superClass

(lldb) p/x studentClass->superclass
(Class) $3 = 0x00000001000014c8 LQPerson

QA

  • 對象的isa指針指向哪里?

instance對象的isa指向class對象
class對象的isa指向meta-class對象
meta-class對象的isa指向基類的meta-class對象

  • OC的類信息存放在哪里?

對象方法、屬性、成員變量、協(xié)議信息,存放在class對象中
類方法,存放在meta-class對象中
成員變量的具體值,存放在instance對象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,041評論 0 9
  • 我們都知道OC對象分為三類,分別是:instance對象(實(shí)例對象)class對象(類對象)meta-class對...
    WolfMobile閱讀 456評論 0 2
  • 最開始讓我有疑問的是在使用類方法,在控制臺(tái)下仍然發(fā)現(xiàn)Class對應(yīng)的有地址,類沒有初始化,為什么會(huì)有地址?這個(gè)地址...
  • 在上一篇文章中我們淺談了Objective-C對象在內(nèi)存中的基本布局,在文章中的末尾部分我留下了兩個(gè)疑問,什么是i...
    SuperMarioGG閱讀 517評論 0 0
  • 每個(gè)人可能都會(huì)經(jīng)歷過一些 平庸的生活,我是一名96后,過往的20年中我真是尼瑪太平庸了,而跑步給了我報(bào)復(fù)平庸的...
    大根日記閱讀 758評論 0 3

友情鏈接更多精彩內(nèi)容