Runtime 與 Aspects

Runtime 之 isa指針

111.png

1.橫向看:實例是對象,類也是對象(類對象),meta類也是對象(原類對象)
這是很重要的一點,希望大家理解,我們這裏忽略上下結構,先看左右結構,從左到右的指向就是之前介紹的runtime源碼中objc_class結構裏isa的指向,Instance指的是我們創建的對象,Subclass(class)就是創建該對象的那個類,注意:創建對象的類本身也是對象,稱爲類對象,類對象中存放的是描述實例相關的信息,例如實例的成員變量,實例方法。
類對象裏的isa指針指向Subclass(meta),Subclass(meta)也是一個對象,是原類對象,原類對象中存放的是描述類相關的信息,例如類方法,在這一過程中,isa的兩次指向很像很像,大家注意理解。
2.縱向看:
superclass指針很容易理解,就是按照繼承關係向上指的,一直到繼承鏈的最上方。

參考:爲什麼object_getClass(obj)與[OBJ class]返回的指針不同

實例方法class 和類方法class

  • 類方法是在meta class裏的,類方法就是把自己返回,而實例方法中是返回實例isa的類
+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

Runtime 之一些方法

Method targetMethod = class_getInstanceMethod(klass, selector);//函數的實例
IMP targetMethodIMP = method_getImplementation(targetMethod);//函數的實現

消息轉發機制

消息轉發機制

Aspects

  • aspects 流程
    1)爲對象增加一個關聯關係:aspects__viewDidLoad關聯內容是 aspectContainer
    2)由對象 和 sel 生成一個identifier
    3) 把identifier增加到container中
    4.1)生成類_Aspects_AspectsViewController, _Aspects_AspectsViewController是 AspectsViewController的子類。
    4.2)修改_Aspects_AspectsViewController的forwardInvocation函數的實現爲_ASPECTS_ARE_BEING_CALLED_
    4.3)_Aspects_AspectsViewController增加方法__aspects_forwardInvocation,__aspects_forwardInvocation的實現爲原forwardInvocation函數的實現。
    4.4)修改對象原類,isa 指針由AspectsViewController 變成 _Aspects_AspectsViewController,。
    5)給類_Aspects_AspectsViewController中增加方法aspects__viewDidLoad 其實現時 原viewDidLoad的實現
    6)給類_Aspects_AspectsViewController 中的方法 viewDidLoad 的實現修改爲_objc_msgForward

  • 我們以在ViewControler的viewWillAppear:方法之後插入一段代碼爲例,來講解hook前後的變化, 在沒有hook之前,ViewController的SEL與IMP關係如下

     

    222.png

333.png

然後,我們再來看看hook後,一個viewWillAppear:的實際調用順序:

  • object收到selector(viewWillAppear:)的消息
  • 找到對應的IMP:_objc_msgForward,執行後觸發消息轉發機制。
  • object收到forwardInvocation:消息
  • 找到對應的IMP:ASPECTS_ARE_BEING_CALLED,執行IMP
  • 向object對象發送aspects_viewWillAppear:,執行最初的viewWillAppear方法的IMP
  • 執行插入的block代碼
  • 如果ViewController無法響應aspects_viewWillAppear,則向object對象發送__aspects_forwardInvocation:來執行最初的forwardInvocation IMP
  • 所以,Aspects是採用了集中式的hook方式,所有的調用最後走的都是一個C函數ASPECTS_ARE_BEING_CALLED

參考
消息轉發機制與Aspects源碼解析

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章