在伯樂(lè)在線看了7篇關(guān)于Objective-C Runtime的博文,確定很詳盡也很深入由捎。但是看起來(lái)有點(diǎn)凌亂,不容易懂。我認(rèn)為Objective-C Runtime主要包括如下幾個(gè)方便次绘。
1、數(shù)據(jù)類型,怎樣定義id邮偎,對(duì)象管跺,class,成員禾进,屬性豁跑,方法,分類泻云,協(xié)議等
2艇拍、消息執(zhí)行邏輯,方法查找宠纯,方法緩存卸夕,動(dòng)態(tài)添加。
3征椒、對(duì)象關(guān)聯(lián)娇哆。
在http://www.reibang.com/p/b1a6c51cfe3e里面的7篇文章說(shuō)得非常全面了,我就換個(gè)角度去總結(jié)吧勃救。OC class的定義如下圖
1碍讨、數(shù)據(jù)類型:
OC 1.0的就不說(shuō)了,那都是歷史了蒙秒。上面可以看到class定義里面還是有isa的Class勃黍。這個(gè)到底是什么呢?帶著問(wèn)題晕讲,再看看object的定義覆获。
struct objc_object { Class isa; };
object里面也包含了Class,這個(gè)Class又是什么呢瓢省?一個(gè)對(duì)象包含一個(gè)Class弄息,我覺(jué)得很正常,也是可以直接理解為就是創(chuàng)造這個(gè)類對(duì)象的類唄勤婚,但是為什么class里面還包含了一個(gè)Class呢摹量?這個(gè)到底是什么呢?這個(gè)類難道又是另外一個(gè)類創(chuàng)建的呢馒胆?細(xì)心的同學(xué)缨称,的確會(huì)這些疑問(wèn)。事實(shí)上OC里面還有一個(gè)隱藏的概念(Meta-class)祝迂,class里面對(duì)應(yīng)的isa就是該類的Meta-class睦尽。我覺(jué)得這個(gè)是OC很神奇的地方,不過(guò)也合理型雳。對(duì)象方法和類方法分來(lái)加載和存放当凡,的確可以節(jié)約內(nèi)存和提高加載的效率山害。
怎么證明我說(shuō)的是對(duì)的,不是瞎扯的呢宁玫?沒(méi)錯(cuò)就是就是想辦法打印類的地址粗恢。
NSLog(@"NSObject's class is %p", [NSObject class]);
NSLog(@"NSObject's class is %p",objc_getClass(class_getName([NSObject class])));
NSLog(@"NSObject's meta class is %p",objc_getMetaClass(class_getName([NSObject class])));
想學(xué)習(xí)的人,還是自己跑一跑代碼吧欧瘪,加深印象,通過(guò)打印的確發(fā)現(xiàn)兩個(gè)地址是不同的匙赞。
2016-04-05 10:24:06.538 test[806:67538] NSObject's class is 0x765000
2016-04-05 10:24:06.538 test[806:67538] NSObject's class is 0x765000
2016-04-05 10:24:06.538 test[806:67538] NSObject's meta class is 0x765014
這樣就證明的確有兩個(gè)類佛掖。那么怎樣知道Meta-class里面是存放類方法呢?沒(méi)錯(cuò)涌庭,就是打印方法表芥被。這個(gè)留給愛(ài)好者去干吧。最后再上一張經(jīng)典的圖坐榆,看不懂的就留言吧拴魄。
說(shuō)完了最基本的類,可以說(shuō)說(shuō)其他的了席镀,
id的定義
typedef struct objc_object *id;
成員列表
方法列表
方法的定義
typedef struct objc_method *Method;
struct objc_method {
SEL method_name? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
char *method_types? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
IMP method_imp? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
}
成員的定義
typedef struct objc_ivar *Ivar;
struct objc_ivar {
char *ivar_name? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
char *ivar_type? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
int ivar_offset? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
#endif
}
IMP的定義
typedef id (*IMP)(id, SEL, ...);
cache的定義
typedef struct objc_cache *Cache
struct objc_cache {
unsigned int mask
/* total = mask + 1 */
OBJC2_UNAVAILABLE;
unsigned int occupied? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
Method buckets[1]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
};
Category的定義
typedef struct objc_category *Category;
struct objc_category {
char *category_name????????????????????????? OBJC2_UNAVAILABLE; // 分類名
char *class_name???????????????????????????? OBJC2_UNAVAILABLE; // 分類所屬的類名
struct objc_method_list *instance_methods??? OBJC2_UNAVAILABLE; // 實(shí)例方法列表
struct objc_method_list *class_methods?????? OBJC2_UNAVAILABLE; // 類方法列表
struct objc_protocol_list *protocols???????? OBJC2_UNAVAILABLE; // 分類所實(shí)現(xiàn)的協(xié)議列表
}
Protocol的定義
typedef struct objc_object Protocol;
最后我們發(fā)現(xiàn)匹中,協(xié)議就是一個(gè)對(duì)象,Category和class很像豪诲。我們可以動(dòng)態(tài)創(chuàng)建協(xié)議顶捷,但是好像沒(méi)有方法修改Category。
還值得注意的是如下的定義屎篱,很有用服赎。
struct objc_super { id receiver; Class superClass; };
2、消息執(zhí)行邏輯
說(shuō)到消息交播,肯定要提到msg_send的重虑,msg_send的原型如下:
objc_msgSend(receiver, selector, arg1, arg2, ...)
receiver是一個(gè)非常值得關(guān)心的東西,例如[self class]和[super class]秦士,那他們的receiver到底是誰(shuí)呢缺厉,上面還特意提到了struct objc_super,事實(shí)上super的receiver依然是self伍宦。
objc_msgSend的執(zhí)行過(guò)程如下芽死,很簡(jiǎn)單明了。但是這只是正常情況的調(diào)用過(guò)程次洼。
好吧关贵,我決定再上一張網(wǎng)上找的圖,這個(gè)圖比較全面卖毁。
這張圖就是比完整了揖曾,包括動(dòng)態(tài)調(diào)用的流程落萎。這個(gè)調(diào)用過(guò)程沒(méi)有例子是很難說(shuō)得清楚的,在這里就不再展開說(shuō)了炭剪,有了這個(gè)圖练链,看伯樂(lè)在線的博文,也比較容易懂了奴拦。有機(jī)會(huì)的話媒鼓,我寫幾個(gè)例子玩一玩吧。
3错妖、對(duì)象關(guān)聯(lián)
類本身是不支持動(dòng)態(tài)添加成員的绿鸣,除非你動(dòng)態(tài)創(chuàng)建類的時(shí)候添加進(jìn)去,一旦類注冊(cè)了就不能再添加了暂氯,協(xié)議也是如此潮模,一旦發(fā)布了,就不能修改了痴施。這樣不科學(xué)呀擎厢,很多時(shí)候我們需要?jiǎng)討B(tài)添加成員,那怎么辦呀辣吃?于是后來(lái)有了對(duì)象關(guān)聯(lián)动遭,當(dāng)然還是可以添加屬性的,setValue等
void objc_setAssociatedObject ( id object,constvoid*key, id value, objc_AssociationPolicy policy );
id objc_getAssociatedObject ( id object,constvoid*key );
void objc_removeAssociatedObjects ( id object );
對(duì)象關(guān)聯(lián)比較簡(jiǎn)單齿尽,也挺常用的沽损。
好了,關(guān)于Objective-C Runtime的總結(jié)就到此為止吧循头。以后有時(shí)間再折騰一下下绵估。。卡骂。