在學(xué)習(xí)KVO時了解到其機理是通過runtime改變isa指針的指向來實現(xiàn)的美澳,但對于isa指針還不是太了解容劳,于是查閱相關(guān)資料在這里做一個整理祟辟。
要了解isa指針首先需要了解類、對象的定義蓖救。
Class:
Object-C類型中類的定義是用Class類型來表示的洪规,實際上它是一個指向objc_class類型的結(jié)構(gòu)體指針,定義如下:
// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
通過objc.h循捺、runtime.h可以看到類的定義:
// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
//父類斩例,如果該類已經(jīng)是最頂層的根類,那么它為NULL。
Class super_class OBJC2_UNAVAILABLE;
//類名
const char *name OBJC2_UNAVAILABLE;
//類的版本信息,默認(rèn)為0
long version OBJC2_UNAVAILABLE;
//類信息巨柒,供運行期使用的一些位標(biāo)識
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;
//協(xié)議鏈表
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
其中:
isa:在OC中需要明確對象和類并沒有本質(zhì)的區(qū)別樱拴,類也是對象,類中有一個指向元類metaClass的isa指針洋满,關(guān)于元類會在后邊進行介紹。
cashe:當(dāng)一個對象接收到某個消息時珍坊,它會根據(jù)isa指針去查找能夠響應(yīng)消息的對象牺勾,每次調(diào)用這個方法后就會緩存到cache中而不必每次都到methodLists遍歷。
objc_object與id:
objc_object表示一個對象阵漏,實際上它表示一個類實例的結(jié)構(gòu)體驻民,定義如下:
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;
可以看到荠呐,對象中包含一個指向其類的isa指針慰毅。當(dāng)我們向一個對象發(fā)送消息時耕姊,Runtime會根據(jù)實例對象的isa指針找到這個實例對象所屬的類白胀,Runtime庫會在類的方法列表及父類的方法列表中去尋找與消息對應(yīng)的selector指向的方法鳄橘。找到后即運行這個方法情臭。
元類(Meta Class):
前面已經(jīng)提到類也是對象飒货,當(dāng)向?qū)ο蟀l(fā)送消息的時會根據(jù)對象isa指針查找所屬類的對應(yīng)方法总棵,對于類方法而言呢,它應(yīng)該去哪查找方法蝗柔?如:
NSString *string = [NSString string];
根據(jù)前面提到的機制闻葵,此時要查找相應(yīng)類對象的+string方法則isa指針需要查找包含這個方法的類,即元類metaClass:類對象所屬的類癣丧。當(dāng)我們向一個對象發(fā)送消息時槽畔,runtime會在這個對象所屬的這個類的方法列表中查找方法;而向一個類發(fā)送消息時胁编,會在這個類的元類的方法列表中查找厢钧。
元類也是一個類,也可以向它發(fā)送一個消息嬉橙,那么它的isa又是指向什么呢坏快?為了不讓這種結(jié)構(gòu)無限延伸下去,Objective-C的設(shè)計者讓所有的元類的isa指向基類的元類憎夷,以此作為它們的所屬類莽鸿。即,任何NSObject繼承體系下的元類都使用NSObject的元類作為自己的所屬類拾给,而基類的元類的isa指針是指向它自己祥得。這樣就形成了一個完美的閉環(huán)。
通過上面的描述蒋得,我們就可以描繪出類的一個繼承體系了级及,如下圖所示:
PS: I am xinghun who is on the road.