Runloop
Runloop是事件接收和分發機制的一個實現。是線程相關的基礎框架的一部分。一個Runloop就是一個事件處理的循環,用來不停的調度工作及處理輸入事件。使用runloop的目的就是讓你的線程
RunLoop的主要目的:
保證程序執行的線程不會被系統終止,如果沒有RunLoop,UIApplicationMain函數執行完畢之后將直接返回,就是說程序一啟動然后就結束,在有工作的時候忙於工作,而沒有工作的時候處於休眠狀態,
什么時候使用Runloop ?
當需要和該線程進行交互的時候才會使用Runloop.
Runloop Mode

一個Runloop可能有幾個mode
Runloop Mode 實際上是 Source,Timer 和 Observer 的集合,不同的 Mode 把不同組的 Source,Timer和Observer 隔絕開來。Runloop` 在某個時刻只能跑在一個 Mode 下,處理這一個 Mode 當中的 Source,Timer 和 Observer。
蘋果文檔中提到的 Mode 有五個,分別是:
NSDefaultRunLoopMode:默認的mode,正常情況下都是在這個mode
NSConnectionReplyMode
NSModalPanelRunLoopMode
NSEventTrackingRunLoopMode:使用這個Mode去跟蹤來自用戶交互的事件(比如UITableView上下滑動)
NSRunLoopCommonModes
iOS 中公開暴露出來的只有 NSDefaultRunLoopMode 和 NSRunLoopCommonModes。 NSRunLoopCommonModes 實際上是一個 Mode 的集合,默認包括 NSDefaultRunLoopMode 和 NSEventTrackingRunLoopMode。
Source
即可以喚醒Runloop的一些事件。比如用戶點擊了屏幕,就會創建一個input source。
source0: 非系統事件source1: 系統時間
Timer
我們經常用的NSTimer就屬於這一類。
Observer
某個observer可以監聽runloop的狀態變化,並作出一定反應。
RunLoop運行流程
經典大圖

沒有事情的時候,Runloop處於休眠狀態。當外部source將其喚醒后,它會依次處理接收到的timer/source,然后再次進入休眠。
常見的面試題:
Runloop和線程是什么關系?
每條線程都有唯一的一個與之對應的RunLoop對象;主線程的RunLoop已經自動創建,子線程的RunLoop需要主動創建;RunLoop在第一次獲取時創建,在線程結束時銷毀
Runloop的mode作用是什么?
指定事件在運行循環中的優先級的,
線程的運行需要不同的模式,去響應各種不同的事件,去處理不同情境模式。(比如可以優化tableview的時候可以設置UITrackingRunLoopMode下不進行一些操作,比如設置圖片等。)
以+scheduledTimerWithTimeInterval:的方式觸發的timer,在滑動頁面上的列表時,timer會暫停回調, 為什么?
滑動scrollView時,主線程的
RunLoop會切換到UITrackingRunLoopMode這個Mode,執行的也是UITrackingRunLoopMode下的任務(Mode中的item),而timer是添加在NSDefaultRunLoopMode下的,所以timer任務並不會執行,只有當UITrackingRunLoopMode的任務執行完畢,runloop切換到NSDefaultRunLoopMode后,才會繼續執行timer。
如何解決在滑動頁面上的列表時,timer會暫停回調?
將
Timer放到NSRunLoopCommonModes中執行即可
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];
NSTImer使用時需要注意什么?
- 注意timer添加到runloop時應該設置為什么mode
- 注意timer在不需要時,一定要調用invalidate方法使定時器失效,否則得不到釋放
