簡單來說:當(dāng)該對象上某個方法,而該對象上沒有實現(xiàn)這個方法的時候齐遵, 可以通過“消息轉(zhuǎn)發(fā)”進(jìn)行解決。
簡單的流程如下塔插,在上一題中也提到過:objc是動態(tài)語言梗摇,每個方法在運行時會被動態(tài)轉(zhuǎn)為消息發(fā)送,即:objc_msgSend(receiver, selector)想许。
objc在向一個對象發(fā)送消息時伶授,runtime庫會根據(jù)對象的isa指針找到該對象實際所屬的類,然后在該類中的方法列表以及其父類方法列表中尋找方法運行流纹,如果糜烹,在最頂層的父類中依然找不到相應(yīng)的方法時,程序在運行時會掛掉并拋出異常unrecognized selector sent to XXX 漱凝。但是在這之前疮蹦,objc的運行時會給出三次拯救程序崩潰的機會:
Method resolution
objc運行時會調(diào)用+resolveInstanceMethod:或者 +resolveClassMethod:,讓你有機會提供一個函數(shù)實現(xiàn)碉哑。如果你添加了函數(shù)并返回 YES挚币,那運行時系統(tǒng)就會重新啟動一次消息發(fā)送的過程,如果 resolve 方法返回 NO 扣典,運行時就會移到下一步妆毕,消息轉(zhuǎn)發(fā)(Message Forwarding)。
Fast forwarding
如果目標(biāo)對象實現(xiàn)了-forwardingTargetForSelector:贮尖,Runtime 這時就會調(diào)用這個方法笛粘,給你把這個消息轉(zhuǎn)發(fā)給其他對象的機會。 只要這個方法返回的不是nil和self湿硝,整個消息發(fā)送的過程就會被重啟薪前,當(dāng)然發(fā)送的對象會變成你返回的那個對象。否則关斜,就會繼續(xù)Normal Fowarding示括。 這里叫Fast,只是為了區(qū)別下一步的轉(zhuǎn)發(fā)機制痢畜。因為這一步不會創(chuàng)建任何新的對象垛膝,但下一步轉(zhuǎn)發(fā)會創(chuàng)建一個NSInvocation對象,所以相對更快點丁稀。
Normal forwarding
這一步是Runtime最后一次給你挽救的機會吼拥。首先它會發(fā)送-methodSignatureForSelector:消息獲得函數(shù)的參數(shù)和返回值類型。如果-methodSignatureForSelector:返回nil线衫,Runtime則會發(fā)出-doesNotRecognizeSelector:消息凿可,程序這時也就掛掉了。如果返回了一個函數(shù)簽名授账,Runtime就會創(chuàng)建一個NSInvocation對象并發(fā)送-forwardInvocation:消息給目標(biāo)對象枯跑。