原理:消息轉(zhuǎn)發(fā):在一個(gè)實(shí)例里邊使用resolveInstanceMethod方法,內(nèi)部動(dòng)態(tài)添加一個(gè)方法class_addMethod去實(shí)現(xiàn)。之所以這樣實(shí)現(xiàn),取決于
OC方法的組成:
SEL(方法名)
IMP(是一個(gè)函數(shù)指針,對(duì)應(yīng)方法實(shí)現(xiàn))
參數(shù)
相當(dāng)于一本書(shū)的目錄,里邊標(biāo)題,對(duì)應(yīng)頁(yè)碼,頁(yè)碼對(duì)應(yīng)具體的模塊內(nèi)容
在動(dòng)態(tài)添加的方法里想要把原有方法傳遞的參數(shù)捕獲到,以便自己使用,需要將自己動(dòng)態(tài)添加實(shí)現(xiàn)的方法進(jìn)行參數(shù)的補(bǔ)全。補(bǔ)全的參數(shù)是方法調(diào)用者(self),和方法編號(hào)(_cmd).
-
那么這兩個(gè)隱士參數(shù)是哪里來(lái)的呢?
OC方法的調(diào)用,底層是objc_msgSend函數(shù),其中包含的參數(shù)有目標(biāo)對(duì)象,方法名(即地址),具體傳遞參數(shù)。因此我們通過(guò)補(bǔ)全參數(shù),通過(guò)方法編號(hào),找到對(duì)應(yīng)實(shí)現(xiàn)方法。
-
緩存
當(dāng)然在發(fā)送消息之前,會(huì)先查找緩存,如果緩存的方法名和傳輸進(jìn)來(lái)要調(diào)度的目標(biāo)方法名結(jié)果一致的話,直接調(diào)用。objc_msgSendunCache不一致的話,從類對(duì)象的方法列表中去查找,如果找到就調(diào)用,并在緩存中備份,cache_getImp。如果類對(duì)象方法和緩存中都沒(méi)有的話,依次往父類層層查詢。
使用的場(chǎng)景:
方法的調(diào)換。
通過(guò)getClassMethod方法,由方法名獲取對(duì)應(yīng)的方法IMP,method_exchange交換方法的IMP(即交換SEL的指向)。此時(shí)原有方法的地址指向新方法的實(shí)現(xiàn),現(xiàn)有方法地址指向原有方法的實(shí)現(xiàn)。
1:對(duì)于table view的reloaddata方法,替換成自己的方法。在對(duì)數(shù)據(jù)進(jìn)行分析后,沒(méi)有數(shù)據(jù)返回的給一個(gè)占位視圖,存在返回?cái)?shù)據(jù)的直接操作使用。
2:字典轉(zhuǎn)模型,自動(dòng)歸解檔操作。