RunLoop簡介
Run 表示運行捍靠,Loop 表示循環(huán)性湿。結(jié)合在一起就是運行循環(huán)的意思。RunLoop就是在程序運行過程中循環(huán)做一些事情。主要應用于以下:
定時器(Timer)统诺、PerformSelector
GCD Async Main Queue
事件響應续徽、手勢識別弟劲、界面刷新
網(wǎng)絡請求
AutoreieasePool
沒有RunLoop支撐,上面的這些都無法實現(xiàn).
作用
1.保持程序的持續(xù)運行
2.處理App中的各種事件(比如觸摸事件叮姑、定時器事件等)
3.節(jié)省了CPU資源,提高程序性能:該做事時做事,該休息時休息
獲取RunLoop對象
iOS中有2套API來訪問和使用RunLoop :
Foundation : NSRunLoop (OC語言里面的)
Core Foundation : CFRunLoopRef (C語言里面的)
NSRunLoop和CFRunLoopRef都代表著RunLoop對象
NSRunLoop是基于CFRunLoopRef的一層OC包裝
CFRunLoopRef是開源的.(CFRunLoopRef參考鏈接)
其實我們很多都是由OC包裝出來的,請看下面:
獲取當前的RunLoop
獲取當前RunLoop和主線程RunLoop
獲取RunLoop
這里注意,地址不一樣,因為NSRunLoop是對CFRunLoopDef做了一層包裝,你可以用OC的NSLog("%@",[NSRunLoop MainRunLoop])獲取對比一下,它的地址就是C語言獲取的地址.主線程只有一個RunLoop.
RunLoop與線程
每條線程都有唯一的一個與之對應的RunLoop對象(一一對應)
RunLoop保存在一個全局的Dictionary里,線程作為key,RunLoop作為value
線程剛創(chuàng)建的時候并沒有RunLoop對象,RunLoop會在第一次獲取它時創(chuàng)建
RunLoop會在線程結(jié)束時銷毀
主線程的RunLoop已經(jīng)自動創(chuàng)建,子線程默認沒有開啟RunLoop.
源碼窺探看一下:CFRunLoopGetCurrent
由于源碼不能像objc直接打開,我們把它拉到項目中查看.
從字典也能看出來是一對一的關系.而且確實是第一次獲取的時候是空的,然后再去創(chuàng)建這個RunLoop.
那我們就繼續(xù)來了解RunLoop內(nèi)部的數(shù)據(jù)結(jié)構(gòu),到底是怎么工作的.
RunLoop相關的類
Core Foundation中關于RunLoop的5個類
1.CFRunLoopRef
2.CFRunLoopModeRef
3.CFRunLoopSourceRef
4.CFRunLoopTimerRef
5.CFRunLoopObserverRef
再看下CFRunLoopRef的底層源碼:
就是上面這個結(jié)構(gòu)體,我們用到的可能就是紅色這些.pthread是線程,每個runloop都會保存這個東西.最后面那個_modes,這個是個集合來著,CFMutableSetRef我們能想到我們自己用的set也是一個集合來著,比如NSMutableSet也是一個集合,所以這個_modes里面是存著一堆的mode.
這個mode就是CFRunLoopModeRef類型,所以里面存儲一堆的CFRunLoopModeRef類型的mode.
而_currentMode也是CFRunLoopModeRef這個類型,所以我們很容易得出一個結(jié)論:
一個RunLoop對象里面有一堆的mode,也就是存在_modes里面,里面只有一個是_currentMode.
我們再窺探一下源碼,看下mode里面存儲的是什么?
所以我們來個總結(jié)的圖:
RunLoop有很多種模式,對應的_currentMode只有一種.
CFRunLoopModeRef
1.CFRunLoopModeRef它是代表RunLoop的運行模式
2.一個RunLoop包含若干個Mode,每個Mode又包含若干個Source0/Source1/Timer/Observer
3.RunLoop啟動時只能選擇其中一個Mode,作為currentMode
4.如果需要切換Mode,只能退出當前RunLoop,再重新選擇一個Mode進入
5.不同組的Source0/Source1/Timer/Observer能分割開來,互不影響
6.如果Mode里面沒有任何Source0/Source1/Timer/Observer,RunLoop會立馬退出
如果只能在一種模式下運行,對性能什么的都有很大好處,比如我在滑動模式下,不考慮不滑動的模式,所以就不會卡頓,順暢很多.還有注意的就是,它切換mode是在循環(huán)里面切換的,所以不會導致程序退出.
常見的mode有2種,其他情況很少見,所以掌握這兩個一般都是沒問題了
1.KCFRunLoopDefaultMode (NSDefaultRunLoopMode):App的默認Mode,通常是主線程是在這個Mode下運行
2.UITrackingRunLoopMode : 界面跟蹤Mode,用于ScrollView追蹤觸摸滑動,保證界面滑動時不受其他Mode影響
RunLoop到底做哪些事?
RunLoop在不停執(zhí)行的時候到底具體做了哪些事?其實是RunLoop在不停循環(huán)的時候,就是處理每個mode下的Source0、Source1砾脑、Timer幼驶、Observer這里面的事件,那我們就來看看這里面具體對應的到底是什么事件.
Source0
觸摸事件、performSelector:onThread:
比如我們的touchbegin這個我們看下下面的代碼:
Source1
基于Port的線程間的通信,系統(tǒng)事件的捕捉.
(兩個線程之間相互傳遞消息的處理,系統(tǒng)事件捕捉,其實也包括觸摸事件,只是把事件捕捉到以后傳遞給Source0).
Timer
NSTimer定時器,performSelector:withObject:afterDelay(這個方法的底層實現(xiàn)也就是NSTimer來實現(xiàn)的)
Observers
用于監(jiān)聽RunLoop的狀態(tài),UI的刷新(BeforeWaiting),Autorelease pool(BeforeWaiting)
(在RunLoop休眠之前都會去執(zhí)行UI的刷新啊韧衣、Autorelease pool的釋放等)
以上這些東西,完全就是我們平時開發(fā)中經(jīng)常寫的代碼,比如設置背景色,設置frame等等.
盅藻,iOS技術(shù)交流群: 711315161,大家一起交流學習畅铭。群內(nèi)有許多技術(shù)大牛氏淑,高手如云,有任何問題顶瞒,歡迎廣大網(wǎng)友一起來交流夸政,群內(nèi)還不定期免費分享中高階iOS學習視頻資料和面試資料包~