淺析IOS中isa指針的作用

在objective-c語言中,isa指針看名稱指的是“是一個”的意思。isa指針是一個指針,具體到代碼中,如果是對象,對象中的isa指針是指向的它的類對象。

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;

如圖中所示,任意對象類型都是struct objc_object  *指針的別名。通過觀察該結構體變量,發現該結構體中只有一個Class類型的變量,它就是OC對象最基本的一個屬性了。那麼這個isa指針是用來做什麼的呢?通過以上代碼,可以發現對象的isa指針類型又是另外一個結構體指針類型struct objc_class *。接下來繼續看這個結構體有什麼內容:

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

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

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

從這個結構體中我們可以看出,這個結構體中同樣有isa指針,這個指針類型就是這個結構體本身。那麼可以大致瞭解到OC類對象是通過遞歸的方式來找到它的根類對象的。除了這個isa指針以外,還有其他的一些屬性:指向父類對象的指針,名字、版本、描述信息、實例佔用內存大小、實例變量列表、方法列表、緩存、遵守的協議列表等。通過這些屬性,就可以得到這個類所有的相關信息了。因此,對象的isa指針指向的可以稱之爲類對象,程序運行時它就指向描述了這個對象所屬的具體類型,而不是id這種動態類型。這樣對象就可以知道剛纔結構體中的所有成員信息了。例如父類是哪個,實例變量有哪些,實例方法有哪些,遵守的協議等。但是這還不夠,因爲對象還有類方法,類變量可以使用,所以類對象也有個isa指針,它指向的就是它的元類。元類中就包含了類對象創建所需要的所有信息。並且這些信息與對象創建不同的是在編譯期就已經確定了。也就是說類對象在程序編譯時就確定了。類對象和元類也有相同點,比如他們都有父類指針super_class,元類的父類指針指向的是元類的父親元類,層層遞進,直到指向NSObject這個OC的Root Class(meta)。然後這個根元類的isa指針指向的是它本身,不知道是啥意思。然後用個圖來表示就是(自己懶得畫了,圖是轉載來的):

舉個例子理解該圖:(->表示繼承關係)

假設 有繼承關係:A->B->C->NSObject,有句代碼:

A *a = [A new];
B *b = [B new];
C *c = [C new];
NSObject *root = [NSObject new];

那麼a這個實例變量就相當於上圖中的Instance of Subclass,b和c就相當於上圖中的Instance of Superclass,root就是Instance of Rootclass。它們的super_class指針就是指向的對應的父類對象。

Class aClass = [a class];
Class bClass = [b class];
Class cClass = [c class];
Class rootClass = [root class];

通過實例變量的class方法就可以得到它們的類對象。也就是它們isa指針指向的內容。根據圖中繼承關係可以表示爲:

aClass -> bClass -> cClass -> rootClass

這也就是類對象的super_class指向的內容。

然後要想獲得元類就不是通過類對象調用class方法得到了,因爲類對象調用class方法得到的是它本身。應該調用的是下面這個方法:

Class aMetaClass = object_getClass(aClass);
Class bMetaClass = object_getClass(bClass);
Class cMetaClass = object_getClass(cClass);
Class rootMetaClass = object_getClass(rootClass);

通過以上這個方法,就可以獲取該類對象所對應的元類。前文說到類對象記錄了類對象的所有信息,最常用的就是類方法。這個元類就是類對象isa指針指向的內容了。元類之間也有

aMetaClass->bMetaClas->cMetaClass->rootMetaClass這種繼承關係存在。

而且,元類isa指針指向的內容就都是相同的了,全都是指向的rootMetaClass。連rootMetaClass它自身isa指針指向的也是它自己。rootMetaClass中定義的就是NSObject類的類方法了,以及NSObject類的內部信息(例如實例方法列表,實例變量列表)。

而NSObject元類就是通過繼承NSObject拿到的NSObject的對象信息的。因此,纔會有NSObject元類繼承自NSObject類這麼一條。也說明了在OC中所有的類的根類都是NSObject類。至於NSObject類的父類,那就不存在了。所以是指向的nil。還有NSObject元類的isa指針指向自身,這個可以理解爲就是一種面向對象概念——萬物皆對象,最終形成一個閉環。

寫在最後

通過以上分析,可以瞭解到isa指針的作用就是描述oc對象的所有信息的。通過這些充足的信息,可以創建出一個結構完整的對象。

 

參考鏈接:https://www.jianshu.com/p/9e975a1cab93

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章