
一. objc_object結(jié)構(gòu)體 objc_class結(jié)構(gòu)體
1.1 objc_object結(jié)構(gòu)體


- isa指針分為
指針型isa和非指針型isa

1.2 objc_class結(jié)構(gòu)體
結(jié)構(gòu)體主要內(nèi)容:
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() {
return bits.data();
}
......
}

1.3 cache_t結(jié)構(gòu)體
struct cache_t {
struct bucket_t *_buckets;//可以理解為一個(gè)數(shù)組
mask_t _mask;
mask_t _occupied;
......
}



cache_t的特點(diǎn):
1.用于快速查找方法執(zhí)行函數(shù)
2.是可增量擴(kuò)展的哈希表結(jié)構(gòu)(增量拓展:結(jié)構(gòu)的量增大,內(nèi)存也會(huì)增大)
3.是局部性原理的最佳應(yīng)用(局部性原理:調(diào)用次數(shù)較高的方法)
1.4 class_data_bits_t結(jié)構(gòu)體
class_data_bits_t包含class_rw_t,class_rw_t內(nèi)包含
struct class_rw_t {
uint32_t flags;
uint32_t version;
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
Class firstSubclass;
Class nextSiblingClass;
char *demangledName;
......
}
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name;
method_list_t * baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
method_list_t *baseMethods() const {
return baseMethodList;
}
};

- 一個(gè)類定義的變量 方法 屬性都在class_data_bits_t這個(gè)成員結(jié)構(gòu)內(nèi)

protocols(協(xié)議) properties(屬性) methods(方法) 是一個(gè)二維數(shù)組,還包括一些分類等

name 類名
ivars 聲明,定義的成員變量
properties 屬性
protocols 協(xié)議
methods 方法
他們是一個(gè)一維數(shù)組


二.類對(duì)象 元類對(duì)象
類對(duì)象 存儲(chǔ)實(shí)例方法列表等信息
元類對(duì)象 存儲(chǔ)類方法列表等信息

問題1:類對(duì)象和元類對(duì)象之間有什么區(qū)別和聯(lián)系?
實(shí)例對(duì)象通過isa指針找到類對(duì)象
類對(duì)象當(dāng)中存儲(chǔ)方法列表等信息
類對(duì)象通過isa指針找到元類對(duì)象、從而可以訪問類方法列表等相關(guān)信息
類對(duì)象和元類對(duì)象都是objc_class數(shù)據(jù)結(jié)構(gòu),因?yàn)槔^承objc_object。所以他們才有isa指針,進(jìn)而可以實(shí)現(xiàn)實(shí)例對(duì)象通過isa指針找到類對(duì)象,進(jìn)而可以訪問實(shí)例方法列表等信息。類對(duì)象通過isa指針找到元類對(duì)象、從而可以訪問類方法列表的相關(guān)信息。
問題2:如果我們調(diào)用的類方法,沒有對(duì)應(yīng)的實(shí)現(xiàn)。但是有同名的實(shí)例方法,會(huì)不會(huì)發(fā)生崩潰,會(huì)不會(huì)產(chǎn)生實(shí)際的調(diào)用?
由于根元類對(duì)象的superclass指針,指向了根類對(duì)象,當(dāng)我們?cè)谠悓?duì)象當(dāng)中查找類方法列表查不到的時(shí)候。會(huì)順著指針去實(shí)例方法列表查找。如果有同名方法,就會(huì)調(diào)用同名方法的實(shí)例方法調(diào)用。
問題3:實(shí)例方法的傳遞過程?
系統(tǒng)根據(jù)當(dāng)前的isa指針。找到它的類對(duì)象,在它的類對(duì)象當(dāng)中查找方法列表。沒有查找到的話,就會(huì)根據(jù)superclass查找父類的類對(duì)象的方法列表。然后根類對(duì)象的方法列表,如果還沒有,就進(jìn)入消息轉(zhuǎn)發(fā)流程。
問題4:類方法的傳遞過程?
通過類對(duì)象的isa指針,找到元類對(duì)象。在它的元類對(duì)象當(dāng)中查找方法列表。沒有查找到的話,就會(huì)根據(jù)superclass查找父類的元類對(duì)象的方法列表。然后順次遍歷方法列表,直到根元類對(duì)象,再到根類對(duì)象。然后根類對(duì)象的方法列表,如果還沒有,就進(jìn)入消息轉(zhuǎn)發(fā)流程。
問題4:類對(duì)象 元類對(duì)象isa指向問題。
元類對(duì)象的isa指針 指向 根元類對(duì)象
根元類對(duì)象isa指針 指向 根元類對(duì)象
根元類對(duì)象的superclass指針指向根類對(duì)象
問題5:打印結(jié)果

結(jié)果都是Phone。因?yàn)榻邮照叨际钱?dāng)前對(duì)象。

問題6:消息傳遞的機(jī)制?
首先通過 哈希查找 查找緩存,緩存沒命中,查當(dāng)前類的方法列表是否命中(對(duì)于已排序好的列表,采用二分查找,對(duì)于沒有排序的列表,采用一般遍歷查找方法)。如果仍然沒命中,逐級(jí)父類方法列表是否命中(父類查找是先通過superclass指針查找父類,遍歷每一個(gè)父類,對(duì)于每一個(gè)父類,又通過緩存查找和當(dāng)前類方法列表查找)。如果都沒有命中,進(jìn)入消息轉(zhuǎn)發(fā)流程。

問題7:[obj foo]和objc_msgSend()函數(shù)之間有什么關(guān)系?
編譯之后,會(huì)在內(nèi)部變成objc_msgSend()函數(shù)調(diào)用。
問題8:消息轉(zhuǎn)發(fā)流程3個(gè)步驟
1.resolvelnstanceMethod(告訴系統(tǒng)是否要解決當(dāng)前的方法實(shí)現(xiàn))
2.forwardingTargetForSelector:(告訴系統(tǒng)這個(gè)實(shí)例方法的調(diào)用應(yīng)該由哪個(gè)對(duì)象來處理,轉(zhuǎn)發(fā)對(duì)象是誰)
3.methodSignatureForSelector:(1.返回方法簽名,調(diào)用forwardInvocation,如果可以處理,轉(zhuǎn)發(fā)結(jié)束 2.如果返回為nil,或者forwardInvocation無法處理,無法找到方法崩潰)

問題9:runtime如何通過Selector找到對(duì)應(yīng)的IMP地址的?
首先查找當(dāng)前實(shí)例對(duì)應(yīng)類對(duì)象的緩存是否有Selector對(duì)應(yīng)的IMP實(shí)現(xiàn),如果緩存命中,就把命中的緩存函數(shù)返回給調(diào)用方。如果緩存沒有命中。根據(jù)當(dāng)前類的方法列表查找Selector對(duì)應(yīng)的IMP事件。當(dāng)前類如果沒有命中,再根據(jù)當(dāng)前類的superClass指針逐級(jí)查找父類的方法列表。然后查找Selector對(duì)應(yīng)的IMP事件。
問題10:@dynamic (動(dòng)態(tài)方法解析)
相當(dāng)于在運(yùn)行時(shí)添加set get方法。而不是在編譯時(shí)聲明好
動(dòng)態(tài)運(yùn)行時(shí)語言將函數(shù)決議推遲到運(yùn)行時(shí)
編譯時(shí)語言在編譯期進(jìn)行函數(shù)決議