概述
? ? ?OC正是由于有了runtime才使得c語(yǔ)言具有了面向?qū)ο蟮哪芰灯剑诔绦虻倪\(yùn)行時(shí)刻拢操,創(chuàng)建,檢查舶替,修改類(lèi)令境、對(duì)象以及類(lèi)、對(duì)象的方法顾瞪。
? ? 為什么會(huì)這么說(shuō)舔庶?OC中的對(duì)象、類(lèi)又到底是一個(gè)什么樣的數(shù)據(jù)結(jié)構(gòu)陈醒,對(duì)象惕橙、類(lèi)又是如何用C來(lái)描述的呢?帶著這樣的問(wèn)題钉跷,我們首先來(lái)看一下在OC中類(lèi)的定義弥鹦。
Class
? ? 在objc/runtime.h中objc_class結(jié)構(gòu)體的定義如下:
struct objc_class {
Class isaOBJC_ISA_AVAILABILITY;//isa指針指向Meta Class,因?yàn)閛bjc類(lèi)本身也是一個(gè)object(對(duì)象),為了處理這個(gè)關(guān)系,runtime創(chuàng)造了Meta Class爷辙,當(dāng)一個(gè)類(lèi)發(fā)送[NSObject alloc]這樣消息時(shí)彬坏,實(shí)際上是把消息發(fā)送給Class object類(lèi)對(duì)象
#if !__OBJC2__
Class super_classOBJC2_UNAVAILABLE;//父類(lèi)
const char *nameOBJC2_UNAVAILABLE;//類(lèi)名
long versionOBJC2_UNAVAILABLE;//類(lèi)的版本信息,默認(rèn)為0
long infoOBJC2_UNAVAILABLE;//類(lèi)信息膝晾,供運(yùn)行時(shí)使用的一些位表示
long instance_sizeOBJC2_UNAVAILABLE;//該類(lèi)的實(shí)例變量大小
struct objc_ivar_list *ivarsOBJC2_UNAVAILABLE;//該類(lèi)的成員變量的鏈表
struct objc_method_list **methodListsOBJC2_UNAVAILABLE;//方法定義的鏈表
struct objc_cache *cacheOBJC2_UNAVAILABLE;//方法緩存栓始,對(duì)象接到一個(gè)消息會(huì)根據(jù)isa指針查找消息對(duì)象,這時(shí)會(huì)在methodLists中遍歷血当,如果cache了幻赚,常用的方法調(diào)用時(shí)就能夠提高調(diào)用的效率。
struct objc_protocol_list *protocolsOBJC2_UNAVAILABLE;//協(xié)議鏈表
#endif
} OBJC2_UNAVAILABLE;
在objc.h中有這樣一個(gè)定義
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
即:OC當(dāng)中任何一個(gè)類(lèi)都是用objc_class這樣一個(gè)結(jié)構(gòu)體來(lái)描述的歹颓。
objc_object與id
? ? objc_object是一個(gè)類(lèi)的實(shí)例結(jié)構(gòu)體坯屿,objc/objc.h中objc_object是一個(gè)類(lèi)的實(shí)例結(jié)構(gòu)體定義如下:
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;
? ? 與objc_class相同,在OC當(dāng)中用一個(gè)結(jié)構(gòu)體描述一個(gè)對(duì)象巍扛;在向object發(fā)送消息的時(shí)候领跛,runtime會(huì)根據(jù)object的isa指針找到這個(gè)實(shí)例的object所屬于的類(lèi),然后在類(lèi)的方法列表以及父類(lèi)的方法列表中尋找對(duì)應(yīng)的方法運(yùn)行撤奸。
? ? id是一個(gè)objc_object結(jié)構(gòu)類(lèi)型的指針吠昭,這個(gè)類(lèi)型的對(duì)象能夠轉(zhuǎn)換任何一種對(duì)象喊括。
Meta Class
? ? 大家可能注意到,一個(gè)對(duì)象的isa指針會(huì)指向它的類(lèi)矢棚。然而在面向?qū)ο蟮氖澜缋镏J玻磺卸际菍?duì)象,即:一個(gè)類(lèi)也是一個(gè)對(duì)象蒲肋,那么問(wèn)題來(lái)了蘑拯,那這個(gè)類(lèi)對(duì)象它的類(lèi)是誰(shuí)呢(可能有點(diǎn)繞大家稍微理解一下這覺(jué)話(huà))?類(lèi)對(duì)象的isa指針又會(huì)指向哪里呢兜粘?
? ?為了解決這個(gè)問(wèn)題申窘,runtime創(chuàng)造了元類(lèi)(Meta Class)。即一個(gè)類(lèi)的是它元類(lèi)的實(shí)例話(huà)孔轴,一個(gè)類(lèi)的isa指針是指向它的元類(lèi)剃法。和對(duì)象一樣,我們向一個(gè)類(lèi)發(fā)送消息的時(shí)候路鹰,isa指針會(huì)在元類(lèi)中以及元類(lèi)的父類(lèi)方法列表尋找對(duì)應(yīng)的方法運(yùn)行贷洲。
? ? 既然一切都是對(duì)象那么元類(lèi)也是對(duì)象,那么元類(lèi)的類(lèi)是誰(shuí)?元類(lèi)的isa指針指向哪里呢晋柱?下面這張經(jīng)典的圖完美了解釋了一些优构,廢話(huà)少說(shuō)上圖:
? ? 即任何一個(gè)元類(lèi)都是根元類(lèi)的對(duì)象,任何一個(gè)元類(lèi)的isa指針都指向了根元類(lèi)雁竞;而根元類(lèi)的isa指針又指向了它自己俩块;形成了一個(gè)閉環(huán),這樣就完美的詮釋了面向?qū)ο蟮氖澜缋锶f(wàn)物皆對(duì)象的概念浓领。(這張圖玉凯,大家一定要好好的理解一下,如果今天看不懂联贩,那么我給的建議是明天再看一遍漫仆,如果明天還看不懂,那就后天泪幌,如果還是不懂盲厌,那就過(guò)段時(shí)間再來(lái)看,如此反復(fù)祸泪,直到成功)
? ? 好吧吗浩,到這里大家應(yīng)該明白了,oc其實(shí)就是在用c的結(jié)構(gòu)體來(lái)描述類(lèi)和對(duì)象没隘,通過(guò)一個(gè)isa指針指來(lái)指去完成了方法的調(diào)用懂扼,對(duì)于c系的同學(xué)來(lái)說(shuō)應(yīng)該不會(huì)有太大的難度。。阀湿。
后面會(huì)繼續(xù)寫(xiě)關(guān)于runtime的知識(shí)赶熟。今天就先到這里吧,打卡陷嘴,下班映砖,回家。灾挨。邑退。
順道拜托,若文中有任何理解不正確的地方歡迎指出