runtime總結

截圖19.png

1.數(shù)據(jù)結構

(1)objc_object
截圖1.png
(2)objc_class
截圖2.png
(3)isa指針

截圖3.png

什么是isa指針?isa分為指針型isa,isa的值代表class地址骇陈,非指針型isa的值的部分代表class的地址扫皱。

(4)isa指向
  • 關于對象定罢,其指向類對象
    截圖4.png
  • 關于類對象,其指向元類對象
    截圖5.png
(5) catch_t
  • 用于快速查找方法執(zhí)行的函數(shù)族购。
  • 可增量擴展哈希表結構
  • 局部性原理的最佳應用
    數(shù)據(jù)結構如下圖
    截圖6.png
(6) class_data_bits_t
  • class_data_bits_t主要是對class_rw_t的封裝
  • class_rw_t代表了類相關的讀寫信息,對class_ro_t的封裝
(7) class_rw_t
截圖7.png
(8) class_ro_t
截圖8.png
(9) method_t

截圖9.png

Type Encodings

  • const char * types
    截圖10.png

    整體數(shù)據(jù)結構
    圖11.png

2.對象、類對象抵拘、元類對象

  • 類對象存儲實例方法列表等信息
  • 元類對象存儲類方法列表等信息
    截圖12.png

    類對象和元類對象之間有什么區(qū)別和聯(lián)系哎榴?
    實例對象可以通過isa指針找到類對象,從而找到類對象中存儲的實例方法列表等信息僵蛛,類對 象可以通過isa指針找到元類對象尚蝌,從而找到元類對象中存儲的類方法列表等信息,類對象和元類對象都是objc_class這種數(shù)據(jù)結構的。對于任何一個元類對象充尉,它的isa指針都指向根元類對象飘言。根元類對象的superClass指針指向根類對象。
    思考
    調用一個類方法喉酌,會沿著元類對象及其元類對象的父類的方法列表依次查找热凹,當類方法在元類對象中找不到時,就會找根類對象中泪电,同名的實例方法實現(xiàn)般妙。
    消息傳遞過程
    調用實例方法, 首先系統(tǒng)會根據(jù)當前實例的isa指針,找到對應的類對象相速,在類對象及其父類的方法列表中依次查找碟渺,直到找到根類對象,如果還是沒用找到突诬,就會走到消息的轉發(fā)流程苫拍。
    調用類方法,系統(tǒng)會根據(jù)當前類的isa指針旺隙,找到對應的元類對象绒极,在元類對象及其元類對象的父類方法列表中依次查找,直到找到根元類蔬捷,如果根元類中也沒有垄提,就會到根類對象中查找同名的實例方法榔袋,如果最終還是沒找到就會走到消息的轉發(fā)流程。

3.消息傳遞

圖13.png

14.png

截圖15.png
#import "Phone.h"
@implementation Phone
- (instancetype)init{
    self = [super init];
    if (self) {
        NSLog(@"%@",NSStringFromClass([self class]));
        NSLog(@"%@",NSStringFromClass([super class]));
    }
    return self;
}
@end
最終的打印結構是一致的铡俐,都是Phone 
(1)緩存查找

給定值SEL凰兑,目標值是對應bucket_t中的IMP

截圖16.png

首先根據(jù)方法選擇器,通過一個函數(shù)映射出bucket_t在數(shù)組中的位置审丘,這一步驟涉及到哈希查找吏够。哈希查找就是根據(jù)給定的一個值,然后經(jīng)過哈希函數(shù)的算法算出的值滩报,就是給定的值的在數(shù)組中的索引位置锅知。
(2)當前類中查找

  • 對于已排序好的列表,采用二分查找算法查找方法對應執(zhí)行函數(shù)脓钾。
  • 對于沒有排序的列表喉镰,采用一般遍歷查找方法對應執(zhí)行函數(shù)。

(3)父類逐級查找


截圖17.png

4.消息轉發(fā)

截圖19.png

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    RuntimeObject *obj = [[RuntimeObject alloc] init];
    [obj test];
    return YES;
}

#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject
- (void)test;
@end

#import "RuntimeObject.h"
@implementation RuntimeObject
+ (BOOL)resolveInstanceMethod:(SEL)sel{
    //如果test方法 打印日志
    if (sel == @selector(test)) {
        NSLog(@"resolveInstanceMethod:");
        return NO;
    }else{
        return [super resolveInstanceMethod:sel];
    }
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"forwardingTargetForSelector");
    return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    if (aSelector == @selector(test)) {
        NSLog(@"methodSignatureForSelector");
        // v代表返回值是void類型   @代表第一個參數(shù)類型是id惭笑,即self
        // : 代表第二個參數(shù)是SEL類型的,即@selector(test) 
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }else{
        return [super methodSignatureForSelector:aSelector];
    }
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSLog(@"forwardInvocation");
}

打印結果:


截圖.png

5.Method-Swizzling

截圖20.png
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    RuntimeObject *obj = [[RuntimeObject alloc] init];
    [obj test];
    return YES;
}

#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject

- (void)test;
- (void)otherTest;

@end

#import "RuntimeObject.h"
#import <objc/runtime.h>
@implementation RuntimeObject
+ (void)load{
     //獲取test方法
     Method test = class_getInstanceMethod(self, @selector(test));
     //獲取otherTest
     Method otherTest = class_getInstanceMethod(self, @selector(otherTest));
     //交換兩個方法的實現(xiàn)
     method_exchangeImplementations(test, otherTest);
    
}
- (void)test{
    NSLog(@"test");
}
- (void)otherTest{
    //實際上調用test的具體實現(xiàn)
    [self otherTest];
    NSLog(@"otherTest");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{  
    //如果test方法 打印日志
    if (sel == @selector(test)) {
        NSLog(@"resolveInstanceMethod:");
        return NO;
    }else{
        return [super resolveInstanceMethod:sel];
    }
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"forwardingTargetForSelector");
    return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    if (aSelector == @selector(test)) {
        NSLog(@"methodSignatureForSelector");
        // v代表返回值是void類型   @代表第一個參數(shù)類型是id生真,即self
        // : 代表第二個參數(shù)是SEL類型的沉噩,即@selector(test) 
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }else{
        return [super methodSignatureForSelector:aSelector];
    }
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSLog(@"forwardInvocation");
}
@end

打印結果


截圖21.png

6.動態(tài)添加方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    RuntimeObject *obj = [[RuntimeObject alloc] init];
    [obj test];
    return YES;
}

#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject
- (void)test;
@end

#import "RuntimeObject.h"
#import <objc/runtime.h>
@implementation RuntimeObject
void testImp(void)
{
    NSLog(@"test invoke");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
     //如果test方法 打印日志
    if (sel == @selector(test)) {
        NSLog(@"resolveInstanceMethod:");
        class_addMethod(self, @selector(test),testImp,"v@:");
        return YES;
    }else{
        return [super resolveInstanceMethod:sel];
    }
}

打印結果


截圖19.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市柱蟀,隨后出現(xiàn)的幾起案子川蒙,更是在濱河造成了極大的恐慌,老刑警劉巖长已,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畜眨,死亡現(xiàn)場離奇詭異,居然都是意外死亡术瓮,警方通過查閱死者的電腦和手機康聂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胞四,“玉大人恬汁,你說我怎么就攤上這事」嘉埃” “怎么了氓侧?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長导狡。 經(jīng)常有香客問我约巷,道長,這世上最難降的妖魔是什么旱捧? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任独郎,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘囚聚。我一直安慰自己靖榕,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布顽铸。 她就那樣靜靜地躺著茁计,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谓松。 梳的紋絲不亂的頭發(fā)上星压,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音鬼譬,去河邊找鬼娜膘。 笑死,一個胖子當著我的面吹牛优质,可吹牛的內容都是我干的竣贪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巩螃,長吁一口氣:“原來是場噩夢啊……” “哼演怎!你這毒婦竟也來了?” 一聲冷哼從身側響起避乏,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤爷耀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拍皮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歹叮,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年铆帽,在試婚紗的時候發(fā)現(xiàn)自己被綠了咆耿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡锄贼,死狀恐怖票灰,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情宅荤,我是刑警寧澤屑迂,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站冯键,受9級特大地震影響惹盼,放射性物質發(fā)生泄漏。R本人自食惡果不足惜惫确,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一手报、第九天 我趴在偏房一處隱蔽的房頂上張望蚯舱。 院中可真熱鬧,春花似錦掩蛤、人聲如沸枉昏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兄裂。三九已至,卻和暖如春阳藻,著一層夾襖步出監(jiān)牢的瞬間晰奖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工腥泥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匾南,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓蛔外,卻偏偏與公主長得像蛆楞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子夹厌,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容