源碼解析
1、查看源碼,發現objc_msgSend是從匯編中開始的。
image.png
2、 如果指針小于等于LNilOrTagged,直接return返回。
image.png
3、 通過isa找到相應的class。
image.png
4、 由上圖可知,接下來CacheLookup(宏定義)找NORMAL參數。
image.png
4.1、CacheHit
image.png
image.png
- NORMAL
- GETIMP 直接返回對應的參數
- LOOKUP
4.2、CheckMiss 找不到的情況
image.png
image.png
- NORMAL --> LGetImpMiss
1、沒有相應的緩存
2、在MethodTableLookup方法列表查找
3、在__class_lookupMethodAndLoadCache3匯編查找
4、在__class_lookupMethodAndLoadCache3 C函數查找
_class_lookupMethodAndLoadCache3
4.1、imp = cache_getImp(cls,sel); --> 回到之前的CacheLookup
4.2、判斷配置
4.3、核心--retry
__4.3.1、cache_getImp又去拿一次(因為OC是動態語言,隨時可以操作修改,防止數據問題)
4.4、如果還是找不到 -->
__4.3.2、getMethodNoSuper_nolock從自己類的方法列表去找,找到了就緩存。
__4.3.3、遞歸去查找父類方法,直到NSObject,找到了就緩存。
image.png
- GETIMP --> __objc_msgSend_uncached
- LOOKUP --> __objc_msgLookup_uncached
5、動態方法解析
- class_resolveMethod
image.png
1、_class_resolveInstanceMethod
2、_class_resolveClassMethod
6、消息轉發
消息轉發流程.png
7、總結
- 方法查找流程大致如下
匯編部分查找-->C函數部分查找-->動態方法解析-->消息轉發-->無法解析(報錯)