分類同名方法調(diào)用原理
1、分類方法在類被加載時(shí)由runtime插入到類對(duì)象/元類對(duì)象的methodList的前面
2、多個(gè)分類時(shí)采用倒序遍歷,把方法匯總到一個(gè)addedList數(shù)組中,所以最后參與編譯的分類方法在addedList的最前面
3、把2中的addedList的方法整體插入到類對(duì)象的methodList的最前面
4、當(dāng)上層在調(diào)用某個(gè)方法時(shí)通過(guò)objc_msgSend方法查找方法列表,找到方法入口地址,完成調(diào)用過(guò)程
5、所以分類和本類有同名方法時(shí)只會(huì)調(diào)用最后一個(gè)參與編譯的分類方法
+ (void)load;
1、load方法在類加載時(shí)由runtime找到load方法的函數(shù)指針,通過(guò)函數(shù)指針直接調(diào)用
2、當(dāng)分類和本類同時(shí)實(shí)現(xiàn)load方法時(shí),所有的load方法都會(huì)調(diào)用
3、先調(diào)用所有本類的load方法,再調(diào)用分類的load方法
4、調(diào)用某個(gè)類的load的方法前會(huì)遞歸調(diào)用其父類的load,即先調(diào)用父類的,最后調(diào)用自己的
5、多個(gè)分類的load方法按照先編譯的先調(diào)用原則
+ (void)initialize;
1、當(dāng)?shù)谝淮谓o某個(gè)類發(fā)送消息時(shí)調(diào)用,且一個(gè)類只初始化一次
2、initialize方法是通過(guò)objc_msgSend方法在元類的方法列表中查找函數(shù),實(shí)現(xiàn)調(diào)用的
3、當(dāng)分類和本類同時(shí)實(shí)現(xiàn)該方法時(shí),只調(diào)用分類的initialize方法(因?yàn)榉诸惖姆椒ㄔ趍ethodList的最前面)
4、當(dāng)初始化某個(gè)類時(shí)會(huì)先遞歸初始化其父類的initialize(如果父類在子類之前已經(jīng)初始化,則該父類不再初始化)
5、由于是通過(guò)objc_msgSend調(diào)用,所以當(dāng)初始化子類時(shí)如果子類沒(méi)有實(shí)現(xiàn)initialize,則會(huì)向上查找實(shí)現(xiàn)了initialize方法的父類,然后調(diào)用該方法。該設(shè)計(jì)會(huì)帶來(lái)一個(gè)父類的initialize方法被多次調(diào)用的現(xiàn)象,但是本質(zhì)還是每個(gè)類只初始化一次,由于子類沒(méi)有實(shí)現(xiàn)而調(diào)用父類的initialize方法,其本質(zhì)是利用父類的initialize方法初始化子類。