基礎(chǔ)總結(jié)(runtime/runloop)

1.runtime介紹(http://www.itdecent.cn/p/ea2d0a6fa8d6)

OC是一門動態(tài)語言,所以它總想辦法把一些決定工作從編譯推遲到運行時。也就是說只有編譯器是不夠的,它還需要一個運行時系統(tǒng)來執(zhí)行編譯后的代碼。這就是Runtime系統(tǒng)存在的意義,它是整個OC的一個基石。

Runtime基本是用C和匯編語言寫的,可見蘋果為動態(tài)系統(tǒng)的高效做出的努力。

Runtime庫主要做下面幾件事:

封裝:在這個庫中,對象可以用C語言中的結(jié)構(gòu)體表示,而方法可以用C函數(shù)來實現(xiàn),另外再加上了一些額外的特性。這些結(jié)構(gòu)體和函數(shù)被runtime函數(shù)封裝后,我們就可以在程序運行時創(chuàng)建,檢查,修改類、對象和它們的方法了。

runtime核心是消息傳遞;

1. 消息發(fā)送流程

?? 確定調(diào)用方法的類是否加載完畢

?? 調(diào)用objc_msgSend方法,給調(diào)用對象發(fā)送消息

?? 對象在方法緩存列表(cache)中查詢是否有對應(yīng)方法,有直接調(diào)用

?? 沒有的話在對象方法列表中查找->父類->>>nsobject 沒找到進入消息動態(tài)解析

2. 消息動態(tài)解析

?? 接收消息對象未找到對應(yīng)的實現(xiàn)方法,調(diào)用solverStanceMethod或者solverClassMethod 看是否進行方法動態(tài)創(chuàng)建方法 創(chuàng)建了就直接使用再次進入消息發(fā)送流程沒有就進入消息轉(zhuǎn)發(fā)

接收消息對象未找到對應(yīng)的實現(xiàn)方法,調(diào)用solverStanceMethod后者solverClassMethod看是否進行方法動態(tài)創(chuàng)建方法 創(chuàng)建了就直接使用再次進入

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

?? 快速轉(zhuǎn)發(fā):forwardingTargertSelector方法進行方法執(zhí)行對象重定向這個快速轉(zhuǎn)發(fā)方法,沒有處理就進入完整消息轉(zhuǎn)發(fā) 調(diào)用methodSignatureForSelector獲得函數(shù)的參數(shù)和返回值類型 創(chuàng)建nsinvocation(求助對象)? 發(fā)送forwardingInvocation消息給目標(biāo)對象 沒獲取到函數(shù)信息? 就會發(fā)出 donsNotrecognizeselector消息 崩潰

應(yīng)用

1.????動態(tài)方法交換 method? swizzling

? ? ? ? 通過 class_getClassMethod()/Class_getInStanceMethod()方法,獲取方法實現(xiàn)地址,通過method_exhangeImplementtations()方法交換兩個方法

?? ? ? 方法的置換在類的 +load方法中調(diào)用

?? ? ? 攔截并替換系統(tǒng)方法

2.????分類添加新屬性?

借助runtime的關(guān)聯(lián)對象特性,幫助我們在運行階段任意屬性關(guān)聯(lián)到一個對象上,實現(xiàn)屬性一樣的效果;

? ? ? 例子:? nsdate分類的year/month/day/hour等

3.????獲取類的詳細信息

包裹屬性列表/成員變量/方法/協(xié)議等

?4. 動態(tài)添加方法和修改屬性變量的值

?5. 歸檔和解檔? 字典和模型的轉(zhuǎn)換(KVC)

6.????KVO實現(xiàn)原理

利用Runtime生成一個中間對象,讓原對象的isa指針指向它,然后重寫 setter方法,插入willChangeValueForKey和didChangeValueForKey方 法。 當(dāng)屬 性變化時會調(diào)用,會調(diào)用這兩個方法通知到外界屬性變化。


runloop

它是一個處理事件的循環(huán)(線程進入這個循環(huán),運行事件處理程序來響應(yīng)傳入的事件),RunLoop的目的是當(dāng)有事件需要處理時,線程是活躍的、忙碌的,當(dāng)沒有事件后,線程進入休眠

Runloop Mode實際上是 Source,Timer 和 Observer 的集合,不同的 Mode 把不同組的Source,Timer和Observer隔絕開來.Runloop 在某個時刻只能跑在一個 Mode 下,處理這一個 Mode 當(dāng)中的 Source,Timer 和 Observer

基本作用

1、保持程序的持續(xù)運行

2、處理App中的各種事件(比如觸摸事件、定時器事件等)

3、節(jié)省CPU資源,提高程序性能:該做事時做事,該休息時休息

應(yīng)用范疇

1、定時器(Timer)、PerformSelector

2、GCD Async Main Queue

3、事件響應(yīng)、手勢識別、界面刷新

4、網(wǎng)絡(luò)請求

5、AutoreleasePool

runloop與線程之間的關(guān)系

1、每條線程都有唯一的一個與之對應(yīng)的RunLoop對象

2、RunLoop保存在一個全局的Dictionary里,線程作為key,RunLoop作為value

3、線程剛創(chuàng)建時并沒有RunLoop對象,RunLoop會在第一次獲取它時創(chuàng)建([NSRunLoop currentRunLoop])

4、RunLoop會在線程結(jié)束時銷毀

5、主線程的RunLoop已經(jīng)自動獲?。▌?chuàng)建),子線程默認沒有開啟RunLoop

runloop內(nèi)部實現(xiàn)邏輯

第一步:首先通知Observers進入Loop 然后處理一些 定時器、事件、block

第二步:事件處理完成之后通知Observers進入休眠狀態(tài)開始休眠 等待消息喚醒

第三步:通知Observers結(jié)束休眠處理一些 定時器、事件、block

autoreleasePool 在何時被釋放

App啟動后,蘋果在主線程 RunLoop 里注冊了兩個 Observer,其回調(diào)都是 _wrapRunLoopWithAutoreleasePoolHandler()

第一個 Observer 監(jiān)視的事件是 Entry(即將進入Loop),其回調(diào)內(nèi)會調(diào)用 _objc_autoreleasePoolPush() 創(chuàng)建自動釋放池,優(yōu)先級最高,保證創(chuàng)建釋放池發(fā)生在其他所有回調(diào)之前

第二個 Observer 監(jiān)視了兩個事件: BeforeWaiting(準(zhǔn)備進入休眠) 時調(diào)用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池;Exit(即將退出Loop) 時調(diào)用 _objc_autoreleasePoolPop() 來釋放自動釋放池,優(yōu)先級最低,保證其釋放池子發(fā)生在其他所有回調(diào)之后

在主線程執(zhí)行的代碼,通常是寫在諸如事件回調(diào)、Timer回調(diào)內(nèi)的。這些回調(diào)會被 RunLoop 創(chuàng)建好的 AutoreleasePool 環(huán)繞著,所以不會出現(xiàn)內(nèi)存泄漏,開發(fā)者也不必顯示創(chuàng)建 Pool 了

PerformSelector 的實現(xiàn)原理

當(dāng)調(diào)用NSObject的performSelecter:afterDelay:后,實際上其內(nèi)部會創(chuàng)建一個Timer并添加到當(dāng)前線程的RunLoop中,所以如果當(dāng)前線程沒有RunLoop,則這個方法會失效

?著作權(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)容

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