+load 底層本質(zhì)。
OC runtime源碼噩死。 objc_init 方法里面 的 load_image 方法回調(diào)里面
- 執(zhí)行 prepare_load_methods 霎迫, 遍歷所有類 調(diào)用schedule_class_load 惶室, 在這個(gè)方法里面 會(huì)先 先將父類實(shí)現(xiàn)了+load方法的類 添加到loadable_classes struct loadable_class {
Class cls; // may be nil
IMP method;
}類型的數(shù)組里面温自。 然后 再將本類也放到這個(gè)數(shù)組里面去。 - 在 prepare_load_methods 方法里面 執(zhí)行完畢 schedule_class_load 在執(zhí)行 把 所有類別 也都遍歷一下 皇钞,找出實(shí)現(xiàn)了+load方法的類別 放到 loadable_categories struct loadable_category {
Category cat; // may be nil
IMP method;
}類型的數(shù)組里面去悼泌。 - 完成以上查找 +load 方法的 類 之后 執(zhí)行 既 load_images 方法里面 完不成了prepare_load_methods 之后 執(zhí)行 call_load_methods方法。 開始調(diào)用+load方法夹界。
- 在 call_load_methods 里面 會(huì)率先執(zhí)行call_class_loads 在這里會(huì)遍歷執(zhí)行 上一步 第2步 添加實(shí)現(xiàn)了+load類的 一個(gè)數(shù)組loadable_classes(里面是loadable_class結(jié)構(gòu)體)馆里,然后通過 *load_method(cls, @selector(load)) 方法 直接調(diào)用類的+load方法
5.在 call_load_methods 里面,執(zhí)行完call_class_loads,之后會(huì)執(zhí)行 call_catergroy_loads, 同理會(huì)遍歷 第2步獲得的 loadable_categroies 結(jié)構(gòu)體數(shù)組鸠踪。 然后 同理通過,然后 會(huì)多一次保護(hù)以舒,判斷 該類別當(dāng)前類 是否存在,并且 完成了+load方法慢哈,之后
*load_method(cls, @selector(load)) 方法 直接調(diào)用類的+load方法
+initialize 底層本質(zhì)。
- 通過 +initialize方法蘋果概念可知永票,+initialize方法是在該類第一次被發(fā)送消息之前調(diào)用卵贱。 就是在查找 方法的 時(shí)候 會(huì)判斷 是否是調(diào)用過 +initialize 。 如果沒有就會(huì)調(diào)用runtime 消息機(jī)制 objc_msgSend(); 調(diào)用+initialize 方法侣集。 所以 他遵循 runtime 消息機(jī)制键俱。特別的一點(diǎn)是 在調(diào)用本類 +initialize方法 之前 會(huì)先調(diào)用父類的 +initialize方法。然后在調(diào)用 本類的 +initialize世分。
總結(jié)编振。 +load 方法 類與分類 父類與父類分類 實(shí)現(xiàn)該方法 才會(huì)執(zhí)行。 不實(shí)現(xiàn) 不會(huì)執(zhí)行臭埋。 類與分類 父類與父類分類 之間的 +load 方法不會(huì)存在覆蓋踪央。 只要 實(shí)現(xiàn) 就會(huì)執(zhí)行。 并且 類與分類 父類與父類分類 的+load 只會(huì)執(zhí)行一次瓢阴。 只會(huì)被調(diào)用一次畅蹂。調(diào)用順序:父類,類荣恐, 分類液斜。 順序。
類執(zhí)行完畢+load方法才會(huì)執(zhí)行分類的 +load 的方法叠穆。 子類與父類+load 方法的執(zhí)行順序與編譯順序無關(guān)少漆,父類先于子類執(zhí)行。(因?yàn)?load call_class_loads 里面是先將父類+load 放到數(shù)組前邊)
然后 父類分類和子類分類 只跟編譯順序有關(guān)硼被。先編譯 先執(zhí)行示损。
+initialize 遵循objc_msgSend()機(jī)制。 執(zhí)行過一次后嚷硫,就不會(huì)再執(zhí)行屎媳。
子類,子類分類和父類 父類分類论巍。 遵循runtime 機(jī)制烛谊。 如果 分類 實(shí)現(xiàn)了 +initialize 就會(huì)覆蓋 類的+initialize方法。編譯順序最后的分類會(huì)覆蓋之前的+initializ嘉汰。
然后源碼分析可知丹禀。 在執(zhí)行子類 +initialize 之前 會(huì)先調(diào)用父類的+initialize方法去執(zhí)行。所以綜上,當(dāng)一個(gè)子類双泪,分類持搜,父類,父類分類 都實(shí)現(xiàn)了+initialize方法的時(shí)候 實(shí)現(xiàn)順序是
父類分類->子類分類焙矛。(分類覆蓋了類的+initialize)葫盼;
特殊。當(dāng)子類跟子類分類都沒有實(shí)現(xiàn)+initialize方法的時(shí)候村斟,根據(jù)runtime機(jī)制贫导。會(huì)去找父類+initialize方法。所以會(huì)出現(xiàn)特殊情況了蟆盹、就是父類的+initialize方法 會(huì)執(zhí)行兩次孩灯。但是 在這個(gè)方法里面 self 是不同。需要注意逾滥。