iOS-底層原理11-動態方法決議走兩次和消息轉發不能為self

《iOS底層原理文章匯總》

上一篇文章中iOS-底層原理10-動態方法決議&消息轉發探索了動態方法決議和消息轉發,有兩個問題還需要探索

問題一:動態方法決議+ (BOOL)resolveInstanceMethod:(SEL)sel里面,沒有對sel方法say666進行重新指定imp,則此動態決議方法+ (BOOL)resolveInstanceMethod:(SEL)sel會走兩次,為什么會走兩次呢???

resloveInstanceMethod兩次@2x.png

28.gif
  • 第一次動態方法決議后,方法返回,是什么時候進入第二次動態方法決議方法的呢???通過打印第二進入前的堆棧情況,獲取堆棧信息如下,得到第二次觸發是在CoreFoundation`-[NSObject(NSObject) methodSignatureForSelector:],后面探索實質為消息的慢速轉發流程。
第二次動態方法決議進入堆棧@2x.png
  • 通過hopper反匯編查看消息轉發流程: ___forwarding_prep_0___->____forwarding___->forwardingTargetForSelector:->methodSignatureForSelector:查看methodSignatureForSelector:源碼實現,進入___methodDescriptionForSelector->class_getInstanceMethod從而在class_getInstanceMethod方法中打斷點調試下。
methodSignatureForSelector源碼@2x.png
methodDescriptionForSelector源碼.png

class_getInstanceMethod斷點調試,進入到消息的慢速查找流程lookUpImpOrForward(nil, sel, cls, LOOKUP_RESOLVER)

class_getInstanceMethod@2x.png
第二次動態方法決議.png
第二次進入resolveInstanceMethod方法.png
  • 第二次動態方法決議還沒找到imp,程序報錯_objc_msgForward_impcache
29.gif
第二次動態方法決議沒找到imp報錯@2x.png

問題二:消息的快速轉發流程中,在forwardingTargetForSelector:方法中動態添加本類的sayHello的Imp,結果程序崩潰,為什么呢???

新建LGStudent的類,將消息轉發給LGStudent的對象,并不會報錯,能正常執行

快速轉發通過runtime添加Imp@2x.png
消息快速轉發本類對象self@2x.png
  • 轉發給LGStudent對象新加的方法程序能正常轉發,通過反編譯代碼,查看反編譯的- (id)forwardingTargetForSelector:(SEL)aSelector源碼
快速轉發給非本類對象@2x.png
rax=rbxforwardingTargetForSelector返回self.png
  • return self,則rax == rbx,進入loc_64a67,發現if (strncmp(r13, "_NSZombie_", 0xa) == 0x0) goto loc_64dc1;,進入goto loc_64dd7
loc_64dc1.png
returnself奔潰報錯.png
消息轉發給本類對象程序崩潰@2x.png
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容