isa和superClass

Objective-C的本質(zhì)

我們平時編寫的Objective-C代碼,底層實現(xiàn)其實都是C\C++代碼,Objective-C的對象、類主要是基于C\C++的結(jié)構(gòu)體實現(xiàn)的

調(diào)用關(guān)系.png

將Objective-C代碼轉(zhuǎn)換為C\C++代碼:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 輸出的CPP文件
如果需要鏈接其他框架,使用-framework參數(shù)。比如-framework UIKit

一個OC對象在內(nèi)存中是如何布局的?
NSObject的底層實現(xiàn).png

OC對象的分類主要分為三個大類

實例對象,instance對象就是通過類alloc出來的對象,每次調(diào)用alloc都會產(chǎn)生新的instance對象object1、object2是NSObject的instance對象(實例對象)
// instance對象,實例對象
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];

它們是不同的兩個對象,分別占據(jù)著兩塊不同的內(nèi)存
instance對象在內(nèi)存中存儲的信息包括

  • isa指針
  • 其他成員變量
實例對象地址.png
類對象objectClass1 ~ objectClass5都是NSObject的class對象(類對象)
// class對象,類對象
// class方法返回的一直是class對象,類對象
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];

它們是同一個對象。每個類在內(nèi)存中有且只有一個class對象

class對象在內(nèi)存中存儲的信息主要包括

  • isa指針

  • superclass指針

  • 類的屬性信息(@property)、類的對象方法信息(instance method)

  • 類的協(xié)議信息(protocol)、類的成員變量信息(ivar)
    ......

  • 類方法信息


    類對象結(jié)構(gòu).png
元類對象

每個類在內(nèi)存中有且只有一個元類對象,元類對象和類對象的內(nèi)存結(jié)構(gòu)一樣,但用途不一樣。

元類對象在內(nèi)存中存儲的信息

  • isa指針
  • superClass的isa指針
元類對象結(jié)構(gòu).png
// meta-class對象,元類對象
// 將類對象當做參數(shù)傳入,獲得元類對象
Class objectMetaClass = object_getClass(objectClass5);
類的獲取

Class objc_getClass(const char *aClassName)
傳入字符串類名
返回對應(yīng)的類對象

Class object_getClass(id obj)
傳入的obj可能是instance對象、class對象、meta-class對象

返回值
如果是instance對象,返回class對象
如果是class對象,返回meta-class對象
如果是meta-class對象,返回NSObject(基類)的meta-class對象

(Class)class、+ (Class)class
返回的就是類對象

\color{red}{實例對象的isa指向的是類對象,類對象的isa指向的是元類對象}

指針

isa

instance的isa指向class
當調(diào)用對象方法時,通過instance的isa找到class,最后找到對象方法的實現(xiàn)進行調(diào)用

class的isa指向meta-class
當調(diào)用類方法時,通過class的isa找到meta-class,最后找到類方法的實現(xiàn)進行調(diào)用

isa指針.png
supclass

supclass指針指向父類的類對象

class對象的superclass指針
當Student的instance對象要調(diào)用Person的對象方法時,會先通過isa找到Student的class,然后通過superclass找到Person的class,最后找到對象方法的實現(xiàn)進行調(diào)用

class的supclass.png

meta-class對象的superclass指針
當Student的class要調(diào)用Person的類方法時,會先通過isa找到Student的meta-class,然后通過superclass找到Person的meta-class,最后找到類方法的實現(xiàn)進行調(diào)用


meta-class的superclass.png
占用內(nèi)存

創(chuàng)建一個實例對象,至少需要多少內(nèi)存?

#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);

創(chuàng)建一個實例對象,實際上分配了多少內(nèi)存?

#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);

isa指針占用8個字節(jié),_no占用4個字節(jié),_age占用4個字節(jié)


student對象內(nèi)部結(jié)構(gòu).png

總結(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找父類

指針路徑.png

\color{red}{64bit之后,isa指針要 \& ISA\_MASK}

ISA_MASK值.png

isa指向地址獲取流程如下圖


isa指向地址獲取.png

\color{red}{superClass指針是直接指向父類的類對象的}

  • 對象調(diào)用方法的軌跡

    通過isa指針指向類對象,在類對象的實例方法列表中找,如果沒找到,通過superclass指針向父類里面找,若果都沒有找到,則會報錯:No known class method for selector

  • 類對象調(diào)用方法的軌跡

    和對象調(diào)用方的軌跡類似,只不過是對象通過isa找到類對象,類對象通過isa找到元類對象,依次向上找,找到基類元類對象里面,如果基類元類對象里面也沒有的話,會去基類的類對象里面找

    舉例說明:
    對象中沒有類方法 +test(),但是父類中有實例方法 -test(),這個時候調(diào)用 [Person test],會依次向上查找,直到再父類類對象中找到實例方法,可以調(diào)用
    消息傳遞方式
    objc_msgSend([Person class], @selector(test))
    objc_msgSend(person, @selector(test))
    isa -> superclass -> suerpclass -> superclass -> .... superclass == nil
    

objc_object結(jié)構(gòu)

objc_object結(jié)構(gòu).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;

當前使用的都是OBJC2,所以這段結(jié)構(gòu)基本上廢棄了,現(xiàn)在為以下結(jié)構(gòu):

struct objc_class {
    Class isa;
    Class superclass;
    cache_t cache;  //方法緩存,是個table
        class_data_bits_t bits;  //  用于獲取具體的類信息,是個table
}

& FAST_DATA_MASK  之后獲得

struct class_rw_t {
    uint32_t
        Class isa;
        Class superclass;
        cache_t cache;  //方法緩存,是個table
        class_data_bits_t bits;  //  用于獲取具體的類信息,是個table
}

總結(jié)

  • 對象的指針指向哪里
    對象的isa指針指向類對象
    類對象的isa指針指向元類的類對象
    元類類對象的isa指針指向基類的元類類對象

  • OC的類信息存放在哪里
    實例對象方法、屬性、成員變量(大小,類型,名字)、協(xié)議信息存放在類對象中
    類方法存放在元類對象中
    成員變量的具體值存放在實例對象

objc4源碼下載

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

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

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