1.運(yùn)行時(shí)簡介
就是在程序運(yùn)行時(shí)候的一些機(jī)制,其中主要是消息機(jī)制,oc在調(diào)用方法的時(shí)候,其實(shí)就是發(fā)送消息;而且oc在編譯階段,是不確定要調(diào)用哪個(gè)函數(shù)的,只有在運(yùn)行的時(shí)候才會(huì)找對(duì)應(yīng)的函數(shù)來調(diào)用
2.消息發(fā)送機(jī)制
2.1方法調(diào)用的本質(zhì)就是利用runtime發(fā)送消息
獲取類對(duì)象,然后去發(fā)送注冊(cè)方法的消息,去調(diào)用,這只是調(diào)用沒有參數(shù)的
objc_msgSend(objc_getClass("NSObject"),sel_registerName("alloc"))
消息機(jī)制的用處:1.可以裝逼。2.可以用runTime調(diào)用類的私有方法
面試時(shí)候會(huì)問:方法是怎么調(diào)用的?
這時(shí)候要知道不同的方法,它存到了什么地方,對(duì)象方法存到對(duì)應(yīng)的類里面,類方法存到了元類里面【meta class】(其實(shí)類也是對(duì)象,它是元類的實(shí)例對(duì)象),而元類是根元類的對(duì)象 root meta class
? ? ? ?1.所以首先要明確去哪個(gè)類查找方法,這時(shí)候就要通過isa指針,它指向的就是你方法所在的類中(每個(gè)類都有一個(gè)方法列表,methordList,在調(diào)用發(fā)方法的時(shí)候,底層是用消息機(jī)制來實(shí)現(xiàn)的,這時(shí)候它會(huì)把方法編號(hào)給你傳過來,可以根據(jù)方法編號(hào),在方法列表中查出所要調(diào)用的方法,在查找的時(shí)候它也是有算法的,因?yàn)橐粋€(gè)類中可能有很多方法,如果一個(gè)一個(gè)遍歷會(huì)很耗時(shí)間,這個(gè)算法是一個(gè)哈希算法,具體怎么算的就不清楚了,反正就是加快了查找的速度)
? ? ? 2.在找到方法之后,其實(shí)只是找到了一個(gè)方對(duì)應(yīng)的函數(shù)名,這時(shí)候要根據(jù)這個(gè)函數(shù)名去找對(duì)應(yīng)的函數(shù)實(shí)現(xiàn)(函數(shù)名其實(shí)就相當(dāng)于函數(shù)的一個(gè)入口)-------(在內(nèi)存中我們是有一塊區(qū)域的:方法區(qū)? 就是通過方法名在這個(gè)區(qū)域找到方法實(shí)現(xiàn)的)
3.交換方法(如果想要在用運(yùn)行時(shí)時(shí)候有提示:在Build Setting中搜索msg,設(shè)置成NO)
這個(gè)的應(yīng)用場景:當(dāng)自定義的一個(gè)類的方法很難維護(hù),并且這個(gè)方法用的還很頻繁,而你目前又想重構(gòu),但卻不想影響當(dāng)前功能,或者是想在系統(tǒng)的一些方法中填一些新的功能,可以使用運(yùn)行時(shí)交換方法,一句話,就是交換兩個(gè)方法的實(shí)現(xiàn):注意如果是要在原方法中添加新的參數(shù)的話,那么是不能使用交換方法的,因?yàn)闆]什么意義,(但是減少參數(shù)是可以的,因?yàn)樗粨Q時(shí)候,參數(shù)也是一一對(duì)應(yīng)進(jìn)行交換的)
1.創(chuàng)建這個(gè)類的分類:如果是系統(tǒng)方法,那么創(chuàng)建分類,如果是自定義的類,那么就直接在類里面重寫load方法,
2.在分類中重寫load方法,load方法是在這個(gè)類第一次調(diào)用的時(shí)候調(diào)用一次,下一次無論是子類還是本類再次調(diào)用都不會(huì)調(diào)用了,initialize這個(gè)類方是:當(dāng)?shù)谝淮渭虞d這個(gè)類的時(shí)候會(huì)調(diào)用一次,但是當(dāng)子類加載時(shí)候還會(huì)調(diào)用一次;
3.交換兩個(gè)方法

4.動(dòng)態(tài)添加方法(動(dòng)態(tài)添加方法首先不需要聲明)
會(huì)問到performSelector這個(gè)方法用沒用過
5.萬能跳轉(zhuǎn):在NSObject的分類中,寫一個(gè)方法,方法需要穿入一個(gè)字典,字典中包括所跳頁面的類名,和所要發(fā)的參數(shù),同時(shí)參數(shù)的名稱要和頁面所接收的參數(shù)屬性名稱一樣,然后運(yùn)用運(yùn)行時(shí),便利屬性名,然后給相同的屬性賦值,用kvc,然后獲得跟控制器,然后跳轉(zhuǎn),具體實(shí)現(xiàn)過程如下圖,這個(gè)可以解耦合



6.動(dòng)態(tài)添加屬性:其實(shí)就是給一個(gè)對(duì)象添加一個(gè)關(guān)聯(lián)
應(yīng)用場景:
1.一般是想給系統(tǒng)的類添加屬性方便開發(fā),一般會(huì)在系統(tǒng)類的分類中,申明get和set方法,然后調(diào)用objc_setAssociate添加關(guān)聯(lián),調(diào)用objc_getAssociate獲取關(guān)聯(lián),這樣就可以動(dòng)態(tài)的將值賦值給這個(gè)關(guān)聯(lián)
2.當(dāng)自己封裝了一個(gè)類,已經(jīng)打包SDK,同時(shí)又不想動(dòng)它,但現(xiàn)在又得添加新的屬性,那么就可以在類的分類中動(dòng)態(tài)添加屬性了