1.Objective-C中方法的調(diào)用在Runtime期間,都會(huì)轉(zhuǎn)為objc_msgSend(receiver, selector, arg1, arg2, ...).默認(rèn)的objc_msgSend會(huì)接收兩個(gè)隱藏的參數(shù),一個(gè)是消息接收者(一般默認(rèn)為self),一個(gè)是方法(默認(rèn)為_(kāi)cmd).
當(dāng)objc_msgSend找不到方法的時(shí)候就會(huì)進(jìn)入消息轉(zhuǎn)發(fā)的流程
1resolveInstanceMethod 或 resolveClassMethod方法是消息轉(zhuǎn)發(fā)的第一步,當(dāng)這個(gè)函數(shù)返回YES時(shí)代表找到了方法就不會(huì)繼續(xù)轉(zhuǎn)發(fā),當(dāng)這個(gè)函數(shù)返回NO時(shí),會(huì)繼續(xù)轉(zhuǎn)發(fā).(備注:respondsToSelector和instancesRepondToSelector兩個(gè)方法就是通過(guò)這個(gè)函數(shù)去檢測(cè)的)
2.在1resolveInstanceMethod內(nèi)部若是沒(méi)有處理這個(gè)情況,那么消息會(huì)進(jìn)一步轉(zhuǎn)發(fā)到(id)forwardingTargetForSelector:(SEL)aSelector這個(gè)函數(shù),這個(gè)函數(shù)返回的是消息的接收者,你可以選擇在這個(gè)方法內(nèi),將消息轉(zhuǎn)發(fā)到另一個(gè)對(duì)象上.
3.若是forwardingTargetForSelector沒(méi)有做任何處理,消息會(huì)到達(dá)(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector這個(gè)函數(shù),這個(gè)函數(shù)返回的是函數(shù)的簽名,在這個(gè)方法內(nèi)部選擇返回函數(shù)簽名,若簽名為nil則消息直接到達(dá)doesNotRecognizeSelector這個(gè)方法,拋出錯(cuò)誤.
4.若是在methodSignatureForSelector方法內(nèi)部返回返回函數(shù)簽名,則消息到達(dá)(void)forwardInvocation:(NSInvocation *)anInvocation這個(gè)函數(shù).這個(gè)函數(shù)中anInvocation參數(shù)包含了函數(shù)簽名,參數(shù),target.SEL等信息.
這是最后一步的轉(zhuǎn)發(fā),若是不處理消息,則消息會(huì)到達(dá)doesNotRecognizeSelector這個(gè)函數(shù),然后拋出錯(cuò)誤.
備注:
1.獲取函數(shù)簽名可以使用[NSMethodSignature signatureWithObjCTypes:"@@:@I"]方法獲取簽名,方法的參數(shù)是函數(shù)的符號(hào)表達(dá)式(個(gè)人理解),其中"@:"表示Selector ,"@:"前面一位表示的是函數(shù)的返回值,后面的表示函數(shù)的參數(shù).例如
-(id)dynaFunc:(NSString *)name :(int)age;
其轉(zhuǎn)換成字符串的表達(dá)式為"@@:@i".具體的Type Encoding請(qǐng)參考Type Encoding.
不過(guò)這種編碼方式很復(fù)雜,可以使用[_dy methodSignatureForSelector:aSelector]方法獲取參數(shù),調(diào)用該方法的對(duì)象是你要轉(zhuǎn)發(fā)的對(duì)象,同時(shí)記得這個(gè)對(duì)象必須和forwardInvocation中Invocation的Target是同一個(gè)對(duì)象.
2.forwardInvocation 該方法中Invocation可以設(shè)置其Target,Arguments,記住設(shè)置參數(shù)時(shí),從索引2開(kāi)始,記得前面說(shuō)的,Objective-C中方法有兩個(gè)隱藏的參數(shù) self ,_cmd 嗎,這就是為什么設(shè)置參數(shù)從索引2開(kāi)始.