_objc_msgForward是一個(gè)函數(shù)指針(和 IMP 的類型一樣)运沦,是用于消息轉(zhuǎn)發(fā)的:當(dāng)向一個(gè)對(duì)象發(fā)送一條消息县习,但它并沒(méi)有實(shí)現(xiàn)的時(shí)候涮母,_objc_msgForward會(huì)嘗試做消息轉(zhuǎn)發(fā)。
結(jié)合《NSObject官方文檔》躁愿,排除掉 NSObject 做的事叛本,剩下的就是_objc_msgForward消息轉(zhuǎn)發(fā)做的幾件事:
-
調(diào)用resolveInstanceMethod:方法 (或 resolveClassMethod:)。允許用戶在此時(shí)為該 Class 動(dòng)態(tài)添加實(shí)現(xiàn)彤钟。如果有實(shí)現(xiàn)了来候,則調(diào)用并返回YES,那么重新開(kāi)始o(jì)bjc_msgSend流程逸雹。這一次對(duì)象會(huì)響應(yīng)這個(gè)選擇器营搅,一般是因?yàn)樗呀?jīng)調(diào)用過(guò)class_addMethod云挟。如果仍沒(méi)實(shí)現(xiàn),繼續(xù)下面的動(dòng)作转质。
-
調(diào)用forwardingTargetForSelector:方法园欣,嘗試找到一個(gè)能響應(yīng)該消息的對(duì)象。如果獲取到休蟹,則直接把消息轉(zhuǎn)發(fā)給它沸枯,返回非 nil 對(duì)象。否則返回 nil 鸡挠,繼續(xù)下面的動(dòng)作辉饱。注意,這里不要返回 self 拣展,否則會(huì)形成死循環(huán)彭沼。
-
調(diào)用methodSignatureForSelector:方法,嘗試獲得一個(gè)方法簽名备埃。如果獲取不到姓惑,則直接調(diào)用doesNotRecognizeSelector拋出異常。如果能獲取按脚,則返回非nil:創(chuàng)建一個(gè) NSlnvocation 并傳給forwardInvocation:于毙。
-
調(diào)用forwardInvocation:方法,將第3步獲取到的方法簽名包裝成 Invocation 傳入辅搬,如何處理就在這里面了唯沮,并返回非ni。
-
調(diào)用doesNotRecognizeSelector: 堪遂,默認(rèn)的實(shí)現(xiàn)是拋出異常介蛉。如果第3步?jīng)]能獲得一個(gè)方法簽名,執(zhí)行該步驟溶褪。
上面前4個(gè)方法均是模板方法币旧,開(kāi)發(fā)者可以override,由 runtime 來(lái)調(diào)用猿妈。最常見(jiàn)的實(shí)現(xiàn)消息轉(zhuǎn)發(fā):就是重寫(xiě)方法3和4吹菱,吞掉一個(gè)消息或者代理給其他對(duì)象都是沒(méi)問(wèn)題的
也就是說(shuō)_objc_msgForward在進(jìn)行消息轉(zhuǎn)發(fā)的過(guò)程中會(huì)涉及以下這幾個(gè)方法:
-
resolveInstanceMethod:方法 (或 resolveClassMethod:)。
-
forwardingTargetForSelector:方法
-
methodSignatureForSelector:方法
-
forwardInvocation:方法
-
doesNotRecognizeSelector: 方法