Runtime 與 Aspects

Runtime 之 isa指針

111.png

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

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

實例方法class 和類方法class

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

- (Class)class {
    return object_getClass(self);
}
Person *obj = [Person new];
    NSLog(@"instance         :%p", obj);
    NSLog(@"class            :%p", object_getClass(obj));
    NSLog(@"meta class       :%p", object_getClass(object_getClass(obj)));
    NSLog(@"root meta        :%p", object_getClass(object_getClass(object_getClass(obj))));
    NSLog(@"root meta's meta :%p", object_getClass(object_getClass(object_getClass(object_getClass(obj)))));
    NSLog(@"---------------------------------------------");
    NSLog(@"class            :%p", [obj class]);
    NSLog(@"meta class       :%p", [[obj class] class]);
    NSLog(@"root meta        :%p", [[[obj class] class] class]);
    NSLog(@"root meta's meta :%p", [[[[obj class] class] class] class]);
instance         :0x135d50810
class            :0x1008d6b58
meta class       :0x1008d6b80
root meta        :0x1a0b6c048
root meta's meta :0x1a0b6c048
---------------------------------------------
class            :0x1008d6b58
meta class       :0x1008d6b58
root meta        :0x1008d6b58
root meta's meta :0x1008d6b58
  • 從打印結(jié)果我們能看到,類也是對象,meta類也是對象,都占有一塊內(nèi)存,
  • 用object_getClass()驗證了我們Class、Object結(jié)構(gòu)模型理論是對的,我們這里特意的打印了root meta class 的isa,發(fā)現(xiàn)果然指向是自己(0x1a0b6c048)
  • 我們發(fā)現(xiàn)調(diào)用class方法的方式不能得到isa的指向鏈,但是第一次調(diào)用是正確的(class的輸出都是0x10ae0e178),為什么?原因就是上面貼出來的class源碼中,我們第一次調(diào)用的class是實例方法,會返回isa的類,但是第二次開始調(diào)用的就是類方法,返回的是本身,所以還是0x10ae0e178,以后無論怎么調(diào)用都是執(zhí)行的類方法,返回的都是本身,所以,用class方法是得不到isa指向鏈的。

Note: 其實這里的難點就在于對 .class 和 object_getClass 的區(qū)分。
.class 當 target 是 Instance 則返回 Class,當 target 是 Class 則返回自身
object_getClass 返回 isa 指針的指向

Runtime 之一些方法

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

消息轉(zhuǎn)發(fā)機制

消息轉(zhuǎn)發(fā)機制

Aspects

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

  • 我們以在ViewControler的viewWillAppear:方法之后插入一段代碼為例,來講解hook前后的變化, 在沒有hook之前,ViewController的SEL與IMP關(guān)系如下


    222.png
333.png

然后,我們再來看看hook后,一個viewWillAppear:的實際調(diào)用順序:

  • object收到selector(viewWillAppear:)的消息
  • 找到對應(yīng)的IMP:_objc_msgForward,執(zhí)行后觸發(fā)消息轉(zhuǎn)發(fā)機制。
  • object收到forwardInvocation:消息
  • 找到對應(yīng)的IMP:ASPECTS_ARE_BEING_CALLED,執(zhí)行IMP
  • 向object對象發(fā)送aspects_viewWillAppear:,執(zhí)行最初的viewWillAppear方法的IMP
  • 執(zhí)行插入的block代碼
  • 如果ViewController無法響應(yīng)aspects_viewWillAppear,則向object對象發(fā)送__aspects_forwardInvocation:來執(zhí)行最初的forwardInvocation IMP
  • 所以,Aspects是采用了集中式的hook方式,所有的調(diào)用最后走的都是一個C函數(shù)ASPECTS_ARE_BEING_CALLED。

參考
消息轉(zhuǎn)發(fā)機制與Aspects源碼解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,058評論 0 9
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言,那么這個「動態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,338評論 0 7
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,892評論 33 466
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 833評論 0 2
  • 本文詳細整理了 Cocoa 的 Runtime 系統(tǒng)的知識,它使得 Objective-C 如虎添翼,具備了靈活的...
    lylaut閱讀 867評論 0 4

友情鏈接更多精彩內(nèi)容