當前位置:成語大全網 - 新華字典 - objc對象調用方法詳細過程

objc對象調用方法詳細過程

實例方法存在類對象中

類方法存在元類對象中(元類其實也是壹個類對象)

我們先看下類對象的結構布局

我們看到壹個類對象就是壹個結構體繼承與objc_object結構體,我們以前的文章中分析過objc_object結構體,這裏簡單的說壹下objc_object, objc_object裏面有壹個isa是壹個***用體.裏面有壹個結構體使用位域來存儲更多的信息.

superclass是指向父類的指針

cache方法的緩存列表

bits& FAST_DATA_MASK的到class_rw_t結構體

在class_rw_t中 methods就是方法的緩存類表

我們以前討論分類的的時候也分析過method_array_t methods;結構

methods是壹個二維數組, 數組裏面的元素是分類的的方法類表

[

[分類方法1a方法,分類方法1b方法],

[分類方法2a方法,分類方法2b方法]

]

我們給壹個對象發消息的時候就會找到methods這個數組裏面然後緩存到cache中,就算給壹個對象調用父類的方法也會緩存到cache中的_buckets, 當往_buckets緩存bucket_t的時候_buckets會檢查是否需要擴容,需要擴容就會清空所有元素然後,在緩存進來.(這個時候以前的緩存就沒有了)

我看到cache結構體中_buckets是壹個數組裏面是bucket_t結構體_key就是方法名字_buckets就相當於壹個離散列表(類似字典)

x0, 寄存器裏面存的是receiver消息接受者

b.le LNilOrTagged //如果receiver為nil跳轉到LNilOrTagged

b.eq LReturnZero // nil check

ret (表示return)

如果對象為nil就return

如果對象不為nil就走到CacheLookup 在緩存中尋找

CacheHit 命中緩存 結果是直接調用方法或者返回imp指針

CheckMiss在緩存中沒有找到

因為CacheLookup NORMAL傳的值是NORMAL 這裏我們暫時只分析__objc_msgSend_uncached

我們再分析MethodTableLookup 發現是個宏

bl __class_lookupMethodAndLoadCache3 意思是跳轉到__class_lookupMethodAndLoadCache3這個方法.

接下來就來到了lookUpImpOrForward

我們分析壹下_class_resolveMethod

如果是實例方法則會調用 _class_resolveInstanceMethod.

我們分析壹下_class_resolveInstanceMethod方法SEL_resolveInstanceMethod 是+ (BOOL)resolveInstanceMethod:(SEL)sel 通過objc_msgSend調用這個類方法, 我們可以重寫這個類方法, 並且在類方法中 動態添加方法

如果我們動態解析沒有做事情 就會來到消息轉發_objc_msgForward_impcache這個imp我們發現在匯編中找到,但是經過分析是沒有源碼的,這裏暫不分析匯編

下面列出動態轉發的幾個方法.

在消息轉發階段如果-forwardingTargetForSelector沒有實現,就會調用- methodSignatureForSelector方法自己返回方法簽名,

然後調用-forwardInvocation返回壹個NSInvocation對象

補充壹點如果 消息轉發階段這個消息是類方法就會調用+forwardingTargetForSelector,+ methodSignatureForSelector

,+ forwardInvocation (雖然沒有暴露出api)

不管是類方法還是對象方法在消息轉發階段, 其實都是消息接受者調用以上的方法.(這樣就可以理解為啥 ,對象方法調用-號類方法調用+號了 因為消息接受者不同)

1消息發送

2動態方法解析

3消息轉發