概覽
我個人了解一個事物的習慣,先去看的的外形,這可以讓我知道他是一個什么東西,其次,了解他被設(shè)計出來的意義,這可以讓我知道他的核心邏輯與服務(wù)目標。這樣在我眼里他是什么,要去做什么就能有一個大概的概念。再從兩個方向出發(fā)向中間對合,挖出他怎樣執(zhí)行目標,如何實現(xiàn)邏輯的行動思想。就可以將其串聯(lián)起來,有一個容易理解的印象。
附一個runloop小demo:https://github.com/AnduinWrynnK/Diablos
RunLoop的外形

runloop表層實現(xiàn)為一個結(jié)構(gòu)體,根據(jù)字面量,內(nèi)部屬性有1.所有加入的mode。2.所有的公開mode。3.所有公開mode的內(nèi)部事件集合。4.當前運行的mode。
RunLoop的設(shè)計意義
RunLoop循環(huán)是一個面向線程的任務(wù)處理機制,他的核心思想是依附于線程的生命周期,有任務(wù)執(zhí)行,無任務(wù)休眠。達到一個在任務(wù)空閑時節(jié)省CPU資源的目的,同時也規(guī)定了一次任務(wù)處理循環(huán)的標準動作。同時,開發(fā)者可以使用RunLoop循環(huán)來實現(xiàn)線程間的通信,拿出優(yōu)化解決方案。
RunLoop的運行原理
基于RunLoop外形,runloop的運行原理是:



runLoop跟隨線程創(chuàng)建,可以處理source1、source0與Timer類型的事件。進入循環(huán)后,依次發(fā)出timer source0的執(zhí)行通知并隨后處理這些任務(wù),再檢查是否有source1的事件,有則直接去處理,處理完重新返回查找source0與Timer類型的事件,沒有則跳過。執(zhí)行完畢后發(fā)出通知線程進入休眠,當收到新的source1消息或手動運行循環(huán)時,喚醒線程重復進入循環(huán)后的步驟。當runloop中source1、source0與Timer類型的事件全部處理完畢或runloop達到超時時間,runloop退出。
與運行原理相關(guān)的概念:
RunLoopMode
runloop是loop->mode->source,三級結(jié)構(gòu),一個runloop可以有多個mode,但是一次只能以一個mode運行,runloop處理mode內(nèi)部的事件或者說與mode類型相同的事件,也只發(fā)送當前mode注冊的通知,并在執(zhí)行完畢時退出,未運行的mode不影響當前的runloop活動。
kCFRunLoopDefaultMode
App的默認Mode,通常主線程是在這個Mode下運行
UITrackingRunLoopMode:
界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動,保證界面滑動時不受其他 Mode 影響
UIInitializationRunLoopMode:
在剛啟動 App 時第進入的第一個 Mode,啟動完成后就不再使用
GSEventReceiveRunLoopMode:
接受系統(tǒng)事件的內(nèi)部 Mode,通常用不到
kCFRunLoopCommonModes:
這是一個占位用的Mode,作為標記kCFRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一種真正的Mode
context
source、Timer與observer都有上下文對象,source與timer的上下文主要內(nèi)容是三個回調(diào)函數(shù)用來在加入循環(huán),執(zhí)行與移出循環(huán)時回調(diào)。而observer的回調(diào)函數(shù)在構(gòu)建CFRunLoopObserverRef時傳入,不需在上下文中指出。
RunLoop的生命周期
runLoop的生命周期大致與此線程的生命周期相同,起于在線程內(nèi)獲取runloop,終于線程結(jié)束。CFDictionaryGetValue(loopsDic, thread)用來在全局查找thread對應(yīng)的runloop,沒有時會用_CFRunLoopCreate()方法創(chuàng)建并將之加入字典。只要是沒有超時且還有未解決的事件,runloop就不會退出,不過這不能保證他是在喚起狀態(tài),source0與timer加入一個休眠線程是無法執(zhí)行的,所以我們將一個事件加入一個runloop之后可以手動喚起他?;蛘呤墙o他加一個port(source1)事件來讓他停留在執(zhí)行port檢測這一步保持他的活躍。
開發(fā)者對RunLoop的實際應(yīng)用
1.nstimer在默認mode下滑動UI時卡頓,換滑動響應(yīng)的model就可以了,或者將timer丟到子線程并保活子線程。
2.在scrollView會大量加載圖片的情況時,可以在runloop通知里結(jié)局這個問題,滑動時不加載圖片,或者加一個緩存數(shù)組,一次循環(huán)只加載一張圖片。
3.通過信號量與runloopObserver方法結(jié)合監(jiān)聽UI卡頓。
4.在runloop中監(jiān)聽崩潰類型,重新運行所有的mode,可以阻止此次崩潰,可是阻止不了第二次。
5.后臺用mach-port?;钜粋€線程用來專門做下載。
6.跟面試官對線。