OC的isa指標

weixin_34402408發表於2017-08-10

一,認識isa指標

首先我們要明確一點:在OC中,任何類的定義都是物件,類和類的例項在本質上沒有區別,任何物件都有isa指標。

isa:是一個Class 型別的指標. 每個例項物件有個isa的指標,他指向物件的類,而Class裡也有個isa的指標, 指向meteClass(元類)。元類儲存了類方法的列表。當類方法被呼叫時,先會從本身查詢類方法的實現,如果沒有,元類會向他父類查詢該方法。同時注意的是:元類(meteClass)也是類,它也是物件。元類也有isa指標,它的isa指標最終指向的是一個根元類(root meteClass).根元類的isa指標指向本身,這樣形成了一個封閉的內迴圈

二,關於objec_class,objec_object

/// An opaque type that represents an Objective-C class.

typedef struct objc_class *Class;

/// A pointer to an instance of a class.

typedef struct objc_object *id;

• Class是一個指向objc_class(類)結構體的指標,而id是一個指向objc_object(物件)結構體的指標。

• objec_object(物件)中isa指標指向的類結構稱為objec_class(該物件的類),其中存放著普通成員變數與物件方法 (“-”開頭的方法)。

• objec_class(類)中isa指標指向的類結構稱為metaclass(該類的元類),其中存放著static型別的成員變數與static型別的方法 (“+”開頭的方法)。

/// Represents an instance of a class.

struct objc_object {

Class isa  OBJC_ISA_AVAILABILITY;

};

•  objec_object(物件)結構體中只有isa一個成員屬性,指向objec_class(該物件的類)。

struct objc_class {

Class isa  OBJC_ISA_AVAILABILITY;//isa指標,指向metaclass(該類的元類)

#if !__OBJC2__

Class super_class//指向objc_class(該類)的super_class(父類)

const char *name//objc_class(該類)的類名

long version//objc_class(該類)的版本資訊,初始化為0,可以通過runtime函式class_setVersion和class_getVersion進行修改和讀取

long info//一些標識資訊,如CLS_CLASS表示objc_class(該類)為普通類。ClS_CLASS表示objc_class(該類)為metaclass(元類)

long instance_size//objc_class(該類)的例項變數的大小

struct objc_ivar_list *ivars//用於儲存每個成員變數的地址

struct objc_method_list **methodLists//方法列表,與info標識關聯

struct objc_cache *cache//指向最近使用的方法的指標,用於提升效率

struct objc_protocol_list *protocols//儲存objc_class(該類)的一些協議

#endif

} OBJC2_UNAVAILABLE;

• objec_class(類)比objec_object(物件)的結構體中多了很多成員,上面就是介紹各個成員的作用。

三,從函式呼叫說起

• 所有的metaclass(元類)中isa指標都是指向根metaclass(元類),而根metaclass(元類)中isa指標則指向自身。

• 根metaclass(元類)中的superClass指標指向根類,因為根metaclass(元類)是通過繼承根類產生的。

• 當我們呼叫某個物件的物件方法時,它會首先在自身isa指標指向的objc_class(類)的methodLists中查詢該方法,如果找不到則會通過objc_class(類)的super_class指標找到其父類,然後從其methodLists中查詢該方法,如果仍然找不到,則繼續通過super_class向上一級父類結構體中查詢,直至根class;

•當我們呼叫某個類方法時,它會首先通過自己的isa指標找到metaclass(元類),並從其methodLists中查詢該類方法,如果找不到則會通過metaclass(元類)的super_class指標找到父類的metaclass(元類)結構體,然後從methodLists中查詢該方法,如果仍然找不到,則繼續通過super_class向上一級父類結構體中查詢,直至根metaclass(元類);

• 這裡有個細節就是要說執行的時候編譯器會將程式碼轉化為objc_msgSend(obj, @selector(makeText)),在objc_msgSend函式中首先通過obj(物件)的isa指標找到obj(物件)對應的class(類)。在class(類)中先去cache中通過SEL(方法的編號)查詢對應method(方法),若cache中未找到,再去methodLists中查詢,若methodists中未找到,則去superClass中查詢,若能找到,則將method(方法)加入到cache中,以方便下次查詢,並通過method(方法)中的函式指標跳轉到對應的函式中去執行。




相關文章