iOS晉級(jí)知識(shí)匯總(二)runtime

Runtime

數(shù)據(jù)結(jié)構(gòu)

  • objc_object
  • objc_class
  • isa指針
  • method_t

objc_object id == objc_object

  • isa_t
  • 關(guān)于isa操作相關(guān)
  • 弱引用相關(guān)
  • 關(guān)聯(lián)對(duì)象相關(guān)
  • 內(nèi)存管理相關(guān)

objc_class class == objc_class 繼承于objc_object

Class superClass

cache_t cache

  • 快速查找方法執(zhí)行函數(shù)
  • 可增量擴(kuò)展的哈希表結(jié)構(gòu)
  • 局部性原理的最佳應(yīng)用
Cache_t.png

class_data_bits_t bits

- class\_data\_bits\_t主要是對(duì)class_rw_t的封裝
- class\_rw\_t代表了類相關(guān)的讀寫信息审残、對(duì)class\_ro\_t的封裝

class_rw_t

  • class_ro_t 代表了類相關(guān)的只讀信息
  • protocols
  • properties
  • methods
class_rw_t.png

class_ro_t

Class_ro_t.png

isa指針

  • 指針型isa 的值代表Class的地址
  • 非指針型isa 的值的部分代表Class的地址
  • 產(chǎn)生這兩種的初衷:我們?cè)趯ぶ穼?shí)際上30~40位數(shù)就可以保證我們尋找到所有class的地址,多出來的位可以存儲(chǔ)一些別的內(nèi)容盟猖,來達(dá)到節(jié)省內(nèi)存的目的
  • 指向問題:
    • 關(guān)于對(duì)象以故,其指向類對(duì)象
    • 關(guān)于類對(duì)象累魔,其指向元類對(duì)象
    • 如果是實(shí)例方法從類對(duì)象查找鞍陨,如果是類方法從元類對(duì)象查找
isa指針.png

method_t

method_t.png

const char * types

type Encodings技術(shù)

Type Encoding.png

數(shù)據(jù)結(jié)構(gòu)總結(jié)

Runtime數(shù)據(jù)結(jié)構(gòu).png

對(duì)象洪燥、類對(duì)象霉祸、元類對(duì)象

  • 類對(duì)象存儲(chǔ)實(shí)例方法列表等信息

  • 元類對(duì)象存儲(chǔ)類方法類表等信息

  • 類對(duì)象和元類對(duì)象都是objc_class數(shù)據(jù)結(jié)構(gòu)轻姿,由于繼承了objc_object數(shù)據(jù)結(jié)構(gòu)所以才有isa指針犁珠,

  • 所以才能實(shí)例對(duì)象找到類對(duì)象訪問它的實(shí)例方法列表等信息,

  • 類對(duì)象通過isa可以找到元類對(duì)象訪問類方法列表等信息

  • 元類對(duì)象的isa指針(包含根元類對(duì)象)都指向根元類對(duì)象

  • 根元類對(duì)象的superclass指向的根類對(duì)象

    • 當(dāng)在跟類中的類方法沒找到互亮,會(huì)指向根類對(duì)象中去查找它的同名的實(shí)例方法

消息傳遞過程

實(shí)例方法消息傳遞過程

1犁享、 調(diào)用了一個(gè)實(shí)例對(duì)象A對(duì)象的實(shí)例方法
2、 通過A實(shí)例對(duì)象的isa指針找到它的類對(duì)象胳挎,類對(duì)象中遍歷方法列表去查找同名的方法實(shí)現(xiàn)饼疙,找到后Runtime發(fā)送消息調(diào)用
3、 如果沒有找到就會(huì)根據(jù)superclass指針指向的父類對(duì)象,并查找其方法列表窑眯。屏积。。直到根類對(duì)象中的方法列表磅甩,如果找到Runtime發(fā)送消息調(diào)用炊林,如果到根類對(duì)象還沒有找到就會(huì)返回nil

類方的消息傳遞過程

1、 調(diào)用一個(gè)類對(duì)象的類方法卷要。
2渣聚、 通過類對(duì)象的isa指針找到元類對(duì)象,元類對(duì)象中遍歷方法列表查找同名的類方法是心啊僧叉,找到后直接調(diào)用
3奕枝、如果沒有找到就會(huì)通過superclass指針指向父元類對(duì)象,并查找其類方法列表瓶堕。隘道。。直到根元類對(duì)象中的類方法列表郎笆,如果找到直接調(diào)用谭梗,如果沒有找到進(jìn)入到消息轉(zhuǎn)發(fā)
4、根元類對(duì)象如果沒有找到會(huì)superclass會(huì)指向根類對(duì)象宛蚓,并查找同名的實(shí)例方法激捏,如果找到直接調(diào)用,如果沒有找到返回nil

消息傳遞

消息傳遞.png
消息傳遞Supr.png
消息傳遞流程.png

1凄吏、緩存查找

例: 給定值是SEL 目標(biāo)值是對(duì)應(yīng)bucket_t的IMP远舅。

  • 首先給定的函數(shù)選擇器通過一個(gè)函數(shù)來映射出bucket_t在數(shù)組當(dāng)中位置,這個(gè)過程是hash查找
  • 哈希查找實(shí)際上竞思,通過給定的一個(gè)值比如說方法的選擇器經(jīng)過哈希函數(shù)的算法酸楚的值實(shí)際上就是給定值在對(duì)應(yīng)數(shù)組當(dāng)中所對(duì)應(yīng)的索引位置表谊。
    • f(key) = key & mask
    • 通過哈希查 解決查找效率的問題
    • 通過哈希查找,找到對(duì)應(yīng)的bucket_t盖喷,就可以拿到IMP

2、當(dāng)前類中查找

對(duì)于已排序好的列表难咕,采用二分查找算法查找方法對(duì)應(yīng)執(zhí)行函數(shù)
對(duì)于沒有排序的列表课梳,采用一般遍歷查找方法對(duì)應(yīng)執(zhí)行函數(shù)

3、父類逐級(jí)查找

父類逐級(jí)查找的過程.png

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

消息轉(zhuǎn)發(fā).png

Method-Swizzling

MethodSwizzling.png
Method method1 = class_getInstanceMethod(self, @selector(test));
Method method2 = class_getInstanceMethod(self, @selector(Mytest));
method_exchangeImplementations(method1, method2);

動(dòng)態(tài)添加方法

編譯的時(shí)候沒有這個(gè)方法余佃,運(yùn)行時(shí)有這個(gè)方法需要調(diào)用performSelector方法,在消息轉(zhuǎn)發(fā)中的第一次處理函數(shù)resolveInstanceMethod動(dòng)態(tài)添加DoThings:Num:方法

+ (BOOL)resolveInstanceMethod:(SEL)sel{

    NSLog(@"%@",NSStringFromSelector(sel));

    if(sel == @selector(DoThings:Num:)){
        class_addMethod([self class], sel, (IMP)MyMethodIMP, "v@:");
        return YES;
    }

    return  [super resolveInstanceMethod:sel];
}

void MyMethodIMP(id self,SEL _cmd,NSString * name,NSInteger num){
    
    NSLog(@"調(diào)用了消息轉(zhuǎn)發(fā)的內(nèi)容");
    NSLog(@"%@",NSStringFromSelector(_cmd));
    NSLog(@"%@",name);
    NSLog(@"%ld",(long)num);
}

動(dòng)態(tài)方法解析

@dynamic

  • 動(dòng)態(tài)運(yùn)行時(shí)語言將函數(shù)決議推遲到運(yùn)行時(shí)暮刃。
    • 當(dāng)我們把一個(gè)屬性標(biāo)示為@dynamic的時(shí)候代表著不需要編譯器在編譯時(shí),為我們生成屬性的setter跟getter方法的具體實(shí)現(xiàn)爆土,而在在具體運(yùn)行時(shí)我們調(diào)用了setter椭懊、geter方法的時(shí)候,再去添加具體的實(shí)現(xiàn)步势。
    • 這種功能也只有動(dòng)態(tài)運(yùn)行時(shí)特性的語言支持
  • 編譯時(shí)語言在編譯期進(jìn)行函數(shù)決議

面試題

nsobject有父類嗎氧猬?

沒有nsobject是根類

當(dāng)在跟類中的類方法沒找到背犯,但是有同名的實(shí)例方法實(shí)現(xiàn),那么會(huì)不會(huì)崩潰盅抚?會(huì)不會(huì)產(chǎn)生實(shí)際的調(diào)用漠魏?

由于根元類對(duì)象的superclass指針指向了根類對(duì)象,去查找實(shí)例同名的實(shí)例方法妄均,如果找到就會(huì)執(zhí)行同名的實(shí)例方法調(diào)用

下圖中打印的是什么柱锹?

筆試題1.png
 [self class]會(huì)轉(zhuǎn)化成     
 objc_msgSend(<#id  _Nullable self#>, <#SEL  _Nonnull op, ...#>)
 phone的實(shí)例對(duì)象,[self class]丰包,通過isa找到phone類對(duì)象禁熏,phone類對(duì)象是沒有class的,通過superclass找到父類的邑彪。瞧毙。。直到查找到根類nsobject锌蓄,有calss的實(shí)現(xiàn)升筏,打印出來的自然是phone
 
 [super class]會(huì)轉(zhuǎn)化成
 objc_msgSendSuper(<#struct objc_super * _Nonnull super#>, <#SEL  _Nonnull op, ...#>)
 
 objc_msgSendSuper實(shí)際的接收者仍然是phone的這個(gè)實(shí)例對(duì)象,objc_msgSendSuper傳遞的含義瘸爽,從phone的這個(gè)實(shí)例對(duì)象的父類開始查找您访,  直到查找到根類nsobject有class的實(shí)現(xiàn),所以打印出來的結(jié)果還是phone
 

打印結(jié)果都是phone

對(duì)頁面的進(jìn)出添加進(jìn)出信息

使用MethodSwizzling來交換viewDidLoadviewWillAppear剪决,在替換代碼中添加一些埋點(diǎn)操作

[obj foo]和objc_msgSend()函數(shù)之間有什么關(guān)系灵汪?

  • 向 obj對(duì)象發(fā)送一條foo的消息,[obj foo]在編譯期處理以后就變成了objc_msgSend(obj,@selector(foo))
  • 由于沒有參數(shù)柑潦,所以 objc_msgSend函數(shù)調(diào)用只有2個(gè)參數(shù)
  • 然后就開始了runtime的消息傳遞過程

runtime如何通過Selector找到對(duì)應(yīng)的IMP地址的享言?

  • 查找當(dāng)前實(shí)例所對(duì)應(yīng)類對(duì)象的緩存,是否有selelctor對(duì)應(yīng)imp實(shí)現(xiàn)如果緩存命中了渗鬼,
    我們就把命中的緩存函數(shù)返回給調(diào)用方览露。
  • 如果緩存沒有就去當(dāng)前類的方法列表查找selector對(duì)應(yīng)的imp實(shí)現(xiàn)
  • 當(dāng)前類如果沒有命中,就根據(jù)當(dāng)前類的superclass逐級(jí)查找父類的方法列表譬胎。差牛。。直到根類對(duì)象堰乔,直到查到selector方法的imp實(shí)現(xiàn)

能否向編譯后的類中增加實(shí)例變量偏化?

class_ro_t ro代表的是readonly

編譯后的類是無法添加實(shí)例變量的。

能否向動(dòng)態(tài)添加的類中增加實(shí)例變量镐侯?

可以的,動(dòng)態(tài)添加的這個(gè)類過程當(dāng)中只要在它調(diào)用注冊(cè)方法之前去完成實(shí)例變量的添加就是可以實(shí)現(xiàn)的

消息傳遞機(jī)制

當(dāng)我們?cè)谙鬟f的過程中如何通過緩存的方法查找侦讨?

isa指針的含義?

  • 非指針類型 isa值的部分代表calss地址
  • 指針類型isa 代表class地址
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市韵卤,隨后出現(xiàn)的幾起案子骗污,更是在濱河造成了極大的恐慌,老刑警劉巖怜俐,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件身堡,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡拍鲤,警方通過查閱死者的電腦和手機(jī)贴谎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來季稳,“玉大人擅这,你說我怎么就攤上這事【笆螅” “怎么了仲翎?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)铛漓。 經(jīng)常有香客問我溯香,道長(zhǎng),這世上最難降的妖魔是什么浓恶? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任玫坛,我火速辦了婚禮,結(jié)果婚禮上包晰,老公的妹妹穿的比我還像新娘湿镀。我一直安慰自己,他們只是感情好伐憾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布勉痴。 她就那樣靜靜地躺著,像睡著了一般树肃。 火紅的嫁衣襯著肌膚如雪蒸矛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天胸嘴,我揣著相機(jī)與錄音莉钙,去河邊找鬼。 笑死筛谚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的停忿。 我是一名探鬼主播驾讲,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了吮铭?” 一聲冷哼從身側(cè)響起时迫,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谓晌,沒想到半個(gè)月后掠拳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纸肉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年溺欧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柏肪。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姐刁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烦味,到底是詐尸還是另有隱情聂使,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布谬俄,位于F島的核電站柏靶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏溃论。R本人自食惡果不足惜屎蜓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔬芥。 院中可真熱鬧梆靖,春花似錦、人聲如沸笔诵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乎婿。三九已至测僵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谢翎,已是汗流浹背捍靠。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留森逮,地道東北人榨婆。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像褒侧,于是被迫代替她去往敵國(guó)和親良风。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谊迄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 分類 用分類干了什么事情? 聲明私有方法 分解體積龐大類文件 把Framework的私有方法公開 特點(diǎn) 運(yùn)行時(shí)決議...
    struggle3g閱讀 32評(píng)論 0 0
  • 1.網(wǎng)絡(luò) 1.網(wǎng)絡(luò)七層協(xié)議有哪些烟央? 物理層:主要功能:傳輸比特流统诺;典型設(shè)備:集線器、中繼器疑俭;典型協(xié)議標(biāo)準(zhǔn)和應(yīng)用:V...
    _我和你一樣閱讀 3,403評(píng)論 1 38
  • 1.說說OC的消息機(jī)制? OC中的方法調(diào)用其實(shí)都是轉(zhuǎn)成了objc_msgSend函數(shù)的調(diào)用粮呢,給receiver(方...
    齊玉婷閱讀 454評(píng)論 0 0
  • Apple相關(guān)源碼地址 在 https://opensource.apple.com/source/[https:...
    Jason1226閱讀 312評(píng)論 0 1
  • 1.weak和assign區(qū)別 修飾變量類型的區(qū)別: weak 只可以修飾對(duì)象。如果修飾基本數(shù)據(jù)類型钞艇,編譯器會(huì)報(bào)錯(cuò)...
    coderjon閱讀 1,019評(píng)論 0 1