聊聊Objective-C的中的對(duì)象

Objective-C中其實(shí)有三種對(duì)象,分別為實(shí)例對(duì)象(instance)、類對(duì)象(class)、元類對(duì)象(meta-class);那這三種對(duì)象有什么關(guān)系呢?以及三種對(duì)象本身存儲(chǔ)了哪些信息呢?這是我們本文要探討的問(wèn)題。

我們知道Objective-C的類可以通過(guò)clang編譯器轉(zhuǎn)換為C++的結(jié)構(gòu)體,也就是說(shuō),Objective-C對(duì)象的本質(zhì)就是結(jié)構(gòu)體,下面通過(guò)實(shí)踐來(lái)證明。

  • 創(chuàng)建一個(gè)命令行項(xiàng)目(這里可以找到),在main.m文件添加如下的代碼
#import <Foundation/Foundation.h>
@interface Person: NSObject {
    int _age;
    double _height;
}
@end

@implementation Person
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

然后使用clang編譯器重寫main.m文件,可指定平臺(tái)iOS和架構(gòu)arm64,在main.m所在的文件夾執(zhí)行如下命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
會(huì)得到一個(gè)main-arm64.cpp的文件,可看到Person類轉(zhuǎn)換為struct Person_IMPL結(jié)構(gòu)體

struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _age;
    double _height;
};

存在上面定義Person類時(shí)聲明的_age_height成員變量,發(fā)現(xiàn)第一個(gè)成員變量是struct NSObject_IMPL結(jié)構(gòu)體,這是NSObjectclang編譯器重寫后對(duì)應(yīng)的結(jié)構(gòu)體,在main-arm64.cpp文件中可找到聲明

struct NSObject_IMPL {
    Class isa;
};

實(shí)例對(duì)象(instance)

Objictive-C實(shí)例對(duì)象是通過(guò)類對(duì)象創(chuàng)建

Person *p1 = [Person new];
Person *p2 = [[Person alloc] init];

實(shí)例對(duì)象分配在堆空間,所以p1、p2指向的內(nèi)存地址都在上;每次創(chuàng)建的都是不同的對(duì)象,所以在內(nèi)存中會(huì)存在很多個(gè)實(shí)例對(duì)象。

struct NSObject_IMPLstruct Person_IMPL合并一下得到下面的結(jié)構(gòu)

struct Person_IMPL {
    Class isa;
    int _age;
    double _height;
};

這也是Person實(shí)例對(duì)象在內(nèi)存中的布局情況。

總結(jié)一下實(shí)例對(duì)象中包含信息

  • isa指針,指向類對(duì)象
  • 成員變量
    其實(shí)isa也是成員變量,只不過(guò)比較特殊,它指向這個(gè)實(shí)例對(duì)象的類對(duì)象。

類對(duì)象(class)

類對(duì)象是對(duì)實(shí)例對(duì)象的描述,描述這個(gè)類實(shí)例對(duì)象有哪些成員變量、屬性、對(duì)象方法、類方法,那這些信息存儲(chǔ)在什么地方呢?(下面提及的數(shù)據(jù)類型這里可以找到)

類對(duì)象聲明為typedef struct objc_class *Class;,再看看struct objc_class結(jié)構(gòu)體,截取一些關(guān)鍵的信息看看

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();
    }
    // ... 還有很多方法,略去
};

superclass指向父類,其他的信息存儲(chǔ)在class_rw_t的結(jié)構(gòu)體中,定義如下

struct class_rw_t {
    const class_ro_t *ro; // 實(shí)例變量信息
    method_array_t methods; // 對(duì)象方法信息
    property_array_t properties; // 屬性信息
    protocol_array_t protocols; // 協(xié)議信息
     // ... 省略其他信息
}

runtime提供這些信息函數(shù)如下

獲取實(shí)例變量

Ivar *
class_copyIvarList(Class cls, unsigned int *outCount)

獲取屬性信息

objc_property_t * 
class_copyPropertyList(Class cls, unsigned int *outCount)

獲取對(duì)象方法

// 第一個(gè)參數(shù)是 *類對(duì)象*,返回的是*對(duì)象方法*;如果是參數(shù)*元類對(duì)象*,返回的是*對(duì)象方法*
Method *
class_copyMethodList(Class cls, unsigned int *outCount)

獲取協(xié)議信息

Protocol * __unsafe_unretained * 
class_copyProtocolList(Class cls, unsigned int *outCount)

struct objc_class繼承objc_object,struct objc_object結(jié)構(gòu)如下

struct objc_object {
private:
    isa_t isa;
    // ...省略方法
}

isa_t是聯(lián)合體,結(jié)構(gòu)如下

union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }
    Class cls;
    uintptr_t bits;
     // ...省略
}

這里面有個(gè) cls成員,這個(gè)就是class指向mata-class的指針。

總結(jié)一下類對(duì)象(class)中存儲(chǔ)的信息

  • isa指針,指向元類的指針
  • superclass指向父類的指針
  • 成員變量(Ivar)的描述信息
  • 屬性(property)的描述信息
  • 對(duì)象方法(Instance Method)的描述信息
  • 遵循協(xié)議(protocol)的描述信息

元類對(duì)象(meta-class)

上面可以看出,meta-class也是一個(gè)Class 類型,與類對(duì)象的數(shù)據(jù)類型時(shí)一樣的,只不過(guò)存儲(chǔ)的信息不同。
元類對(duì)象(meta-class)存儲(chǔ)的信息有

  • isa指針,指向基類(NSObject)元類(meta-class)的指針,所有元類(meta-class)isa指針都指向NSObject元類的指針。
  • superclass指向父類的元類(meta-class)的指針
  • 類方法(class Method)的描述信息

總結(jié)

上面講了實(shí)例對(duì)象的內(nèi)存布局,以及實(shí)例對(duì)象(instance)、類對(duì)象(class)、元類對(duì)象(meta-class)之間的關(guān)系,最后用一張圖來(lái)說(shuō)明它們之間的關(guān)系。

class-inherit.png

參考文章

詳解Objective-C的isa與meta-class
Objective-C 中的 Meta-class 是什么?

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

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

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