iOS底層原理 - 《Class探索》

Class定義

Class是一個(gè)objc_class * 類型結(jié)構(gòu)體指針
objc_class *是Objective-C2.0版本已經(jīng)廢除
在Objective-C2.0版本中,使用Class替代objc_class *

//在objc/objc.h系統(tǒng)文件中定義如下

typedef struct objc_class *Class;

objc_class結(jié)構(gòu)體定義

理解時(shí)出現(xiàn)小坑.下面的定義才是2.0版本的正解
網(wǎng)上的博客好多都是直接截取以這個(gè)來解釋了,但是我看了OBJC_ISA_AVAILABILITY宏定義(下面有代碼片段)之后,無法理解,為什么都說廢除了,但是網(wǎng)上的博客好多都按照廢除的那個(gè)來解釋呢?
然后繼續(xù)查資料然后在Objective-C的runtime機(jī)制01-數(shù)據(jù)結(jié)構(gòu)和內(nèi)部關(guān)系圖找到了一個(gè)合理的解釋.
(其實(shí)不用懷疑,確實(shí)是2.0版本已廢除了,但是網(wǎng)上的博客好多都按照廢除的那個(gè)來解釋)

/// 在objc/runtime.h系統(tǒng)文件中定義如下

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 *` */

1、OBJC_ISA_AVAILABILITY 這里標(biāo)明了已經(jīng)在Objective-C2.0版本廢除了,但網(wǎng)上的大部分還是直接這個(gè)來解釋

用來標(biāo)記isa對(duì)象是否過期有效如果是Objective-C2.0版本,就表示廢棄,否則就是依然有效.
如果是__OBJC2__版本(Objective-C第二版本),定義OBJC_ISA_AVAILABILITYattribute((deprecated))過期標(biāo)記,否則就依然有效

//在objc/objc-api.h中

/* OBJC_ISA_AVAILABILITY: `isa` will be deprecated or unavailable 
* in the future */
#if !defined(OBJC_ISA_AVAILABILITY)
#   if __OBJC2__
#       define OBJC_ISA_AVAILABILITY  __attribute__((deprecated))
#   else
#       define OBJC_ISA_AVAILABILITY  /* still available */
#   endif
#endif

2、!OBJC2

表示非Object c 2.0的版本,Object c是從1.0發(fā)展到現(xiàn)在的2.0,這個(gè)聲明是為了兼容1.0的Object c,若是Object c 2.0的話,可見objc_class與objc_object的定義是一樣的,都是只有一個(gè)isa指針,所以說在Object c里面,類也是一個(gè)對(duì)象

objc_class結(jié)構(gòu)體定義

下面??這個(gè)是蘋果官網(wǎng)的源碼片段objc4-680,objc_class結(jié)構(gòu)體定義在OC的2.0版本定義

//-------- [file:objc-runtime-new.h] --------
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
    ......
}

//-------- [file:objc-private.h] --------
typedef struct objc_class *Class;
typedef struct objc_object *id;

struct objc_object {
private:
    isa_t isa;
    ......
}

union isa_t 
{
    ......
    Class cls;
    uintptr_t bits;
    ......
}

作者:qiushuitian
鏈接:http://www.itdecent.cn/p/50f2bcfc8fb7
  • objc_objectobjc_class關(guān)系

Runtime中定義了一個(gè)叫做 objc_object 的結(jié)構(gòu)體,代表OC層的對(duì)象
定義了一個(gè)objc_class的結(jié)構(gòu)體,代表OC層的,可以清楚看到, objc_class是繼承objc_object的,因此,也是一個(gè)objc_object的對(duì)象

  • objc_object中的成員變量isa

objc_object中有個(gè)isa_t 的成員變量isa,isa_t是個(gè)聯(lián)合體,我們只關(guān)心它的Class cls的聯(lián)合部分。而Class又是個(gè)objc_class *。每個(gè)對(duì)象里面有個(gè)isa的成員變量,指向它代表一個(gè)類的東西。從OC的角度看,每個(gè)對(duì)象都能從isa中尋找到它的類的相關(guān)信息。

類與元類

1.類對(duì)象(class object)
編譯器會(huì)知道類的各種信息,如類名,類屬性,類方法等等,然后在運(yùn)行時(shí),編譯器會(huì)根據(jù)類描述信息進(jìn)行生成類對(duì)象(class object),這個(gè)對(duì)象是描述類信息的,是一個(gè)單例對(duì)象(singleton),這個(gè)好理解.因?yàn)檎麄€(gè)生命周期內(nèi)唯一一個(gè)類
2.元類對(duì)象(metaclass object):
類對(duì)象既然是objc_object類型,當(dāng)然也有個(gè)isa的指針.這個(gè)isa指針指向的對(duì)象就是元類對(duì)象(metaclass object)。元類對(duì)象存儲(chǔ)的信息描述的是類對(duì)象的

其中虛線 isa指針,實(shí)線superclass

靜態(tài)描述圖

isa指針指向圖例

程序啟動(dòng)之后,會(huì)根據(jù)編譯時(shí)的類的信息,在runtime環(huán)境中構(gòu)建相應(yīng)的類對(duì)象和元類對(duì)象。
元類對(duì)象isa都指向根類,類對(duì)象的isa指向自己的元類對(duì)象,并且是個(gè)單例,構(gòu)建相應(yīng)的superclass等。這樣,啟動(dòng)之后,runtime就知道有些啥類,他們能干嘛,他們之間的關(guān)系是什么樣了。
運(yùn)行時(shí),如果遇到創(chuàng)建OC某個(gè)類的實(shí)例對(duì)象(instance object),分配空間之后,把isa指針指向?qū)ο蟮念悓?duì)象(class object),這樣,對(duì)于這個(gè)OC對(duì)象,也就能知道類的信息。
為啥搞得那么復(fù)雜
C語言不是動(dòng)態(tài)語言。OC作為C的超集,要實(shí)現(xiàn)動(dòng)態(tài),就要把類的描述之類的東西從編譯階段挪到運(yùn)行階段。那么在運(yùn)行階段,就需要有類對(duì)象(class object),元類對(duì)象(metaclass object)等等對(duì)象化的東西來處理OC類的信息。runtime就這么玩的。

參考博客:

1、Objective-C的runtime機(jī)制01-數(shù)據(jù)結(jié)構(gòu)和內(nèi)部關(guān)系圖[推薦閱讀]
2、iOS底層原理總結(jié) - 探尋OC對(duì)象的本質(zhì)[推薦閱讀]
3、iOS Class結(jié)構(gòu)分析

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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