1.runtime介紹(http://www.reibang.com/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)中查詢是否有對應方法,有直接調(diào)用
?? 沒有的話在對象方法列表中查找->父類->>>nsobject 沒找到進入消息動態(tài)解析
2. 消息動態(tài)解析
?? 接收消息對象未找到對應的實現(xiàn)方法,調(diào)用solverStanceMethod或者solverClassMethod 看是否進行方法動態(tài)創(chuàng)建方法 創(chuàng)建了就直接使用再次進入消息發(fā)送流程沒有就進入消息轉(zhuǎn)發(fā)
接收消息對象未找到對應的實現(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消息給目標對象 沒獲取到函數(shù)信息? 就會發(fā)出 donsNotrecognizeselector消息 崩潰
應用
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方 法将宪。 當屬 性變化時會調(diào)用,會調(diào)用這兩個方法通知到外界屬性變化橡庞。
runloop
它是一個處理事件的循環(huán)(線程進入這個循環(huán)较坛,運行事件處理程序來響應傳入的事件),RunLoop的目的是當有事件需要處理時扒最,線程是活躍的丑勤、忙碌的,當沒有事件后吧趣,線程進入休眠
Runloop Mode實際上是 Source法竞,Timer 和 Observer 的集合,不同的 Mode 把不同組的Source,Timer和Observer隔絕開來.Runloop 在某個時刻只能跑在一個 Mode 下强挫,處理這一個 Mode 當中的 Source岔霸,Timer 和 Observer
基本作用
1、保持程序的持續(xù)運行
2俯渤、處理App中的各種事件(比如觸摸事件呆细、定時器事件等)
3、節(jié)省CPU資源八匠,提高程序性能:該做事時做事絮爷,該休息時休息
應用范疇
1、定時器(Timer)梨树、PerformSelector
2坑夯、GCD Async Main Queue
3、事件響應抡四、手勢識別柜蜈、界面刷新
4仗谆、網(wǎng)絡請求
5、AutoreleasePool
runloop與線程之間的關(guān)系
1跨释、每條線程都有唯一的一個與之對應的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(準備進入休眠) 時調(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)原理
當調(diào)用NSObject的performSelecter:afterDelay:后叼丑,實際上其內(nèi)部會創(chuàng)建一個Timer并添加到當前線程的RunLoop中,所以如果當前線程沒有RunLoop关翎,則這個方法會失效