什么是Runloop
運(yùn)行循環(huán)寄摆,在程序運(yùn)行中做事情
- 定時(shí)器,performSelector
- GCD Async queue
- 事件響應(yīng),手勢(shì)識(shí)別圆凰,頁(yè)面刷新
- 網(wǎng)絡(luò)請(qǐng)求
- autoreleasepool
卡頓檢測(cè) http://www.reibang.com/p/d0aab0eb8ce4
新開(kāi)線程,用 while YES 加一個(gè)信號(hào)量体箕,在 回調(diào)(runloop循環(huán)會(huì)調(diào)用)中去打開(kāi)信號(hào)量专钉,計(jì)算次數(shù)
卡頓時(shí)runloop在做什么 activity == kCFRunLoopBeforeSources || activity == kCFRunLoopAfterWaiting
休眠時(shí) before Waiting
1s 看任務(wù)情況大概幾個(gè)幾十個(gè)循環(huán)都有可能
runloop底層結(jié)構(gòu)
結(jié)構(gòu)體,內(nèi)部有_pthread/commonModes/commonModelItems/_currentMode 和modes
其中 modes 里面裝的是 各種模式累铅。
每個(gè)模式里面有 name跃须, source0,source1娃兽,obsevers菇民,timer (都是set)
- 一個(gè)runloop包含若干mode,每個(gè)mode包含若干 source0/source1/timer/Observer
- 每次只能選擇一個(gè)mode投储,切換mode需要退出當(dāng)前l(fā)oop第练,重新選擇
- 不同組的source0/source1/timer/observer互不干擾
- mode沒(méi)有事件會(huì)立即退出
runloop與線程
每條線程都有與之對(duì)應(yīng)的runloop對(duì)象
runloop保存在全局的dictionary,key=線程玛荞,value=runloop
線程剛創(chuàng)建不會(huì)有runloop對(duì)象娇掏,第一次獲取時(shí)創(chuàng)建
runloop在線程結(jié)束時(shí)銷(xiāo)毀
主線程默認(rèn)開(kāi)啟runloop,子線程默認(rèn)沒(méi)有開(kāi)啟
常見(jiàn)2種mode
default 默認(rèn)
tracking scrollview
runloop運(yùn)行邏輯
- 通知 observers 進(jìn)入loop
- 通知 observers 即將處理timer
- observers 即將處理sources
- 處理 blocks
- 處理source0
- 如存在source1 ->8
- 通知 observers 開(kāi)始休眠
- 通知 observers 結(jié)束休眠 (處理 timer勋眯,GCD Async To Main Queue婴梧,source1)
- 處理 Blocks
- 根據(jù)結(jié)果繼續(xù) runloop或者 退出
- 通知 observers 退出 loop
Source0:觸摸事件下梢,performSelector:onTnread:
Source1:port通信,系統(tǒng)事件捕捉
Source1 :基于mach_Port的,來(lái)自系統(tǒng)內(nèi)核或者其他進(jìn)程或線程的事件塞蹭,可以主動(dòng)喚醒休眠中的RunLoop(iOS里進(jìn)程間通信開(kāi)發(fā)過(guò)程中我們一般不主動(dòng)使用)孽江。mach_port大家就理解成進(jìn)程間相互發(fā)送消息的一種機(jī)制就好, 比如屏幕點(diǎn)擊, 網(wǎng)絡(luò)數(shù)據(jù)的傳輸都會(huì)觸發(fā)sourse1。
? Source0 :非基于Port的 處理事件浮还,什么叫非基于Port的呢竟坛?就是說(shuō)你這個(gè)消息不是其他進(jìn)程或者內(nèi)核直接發(fā)送給你的。一般是APP內(nèi)部的事件, 比如hitTest:withEvent的處理, performSelectors的事件.
簡(jiǎn)單舉個(gè)例子:一個(gè)APP在前臺(tái)靜止著钧舌,此時(shí)担汤,用戶(hù)用手指點(diǎn)擊了一下APP界面,那么過(guò)程就是下面這樣的:
我們觸摸屏幕,先摸到硬件(屏幕)洼冻,屏幕表面的事件會(huì)被IOKit先包裝成Event,通過(guò)mach_Port傳給正在活躍的APP , Event先告訴source1(mach_port),source1喚醒RunLoop, 然后將事件Event分發(fā)給source0,然后由source0來(lái)處理崭歧。
Timers:NSTimer,performSelector:withObject:afterDelay:
Observes: 監(jiān)控runloop狀態(tài)撞牢,UI刷新(before waiting)率碾,AutoreleasePool(before waiting)
runloop運(yùn)用
- 線程保活
- 解決NSTimer滑動(dòng)停止
- 監(jiān)控卡頓屋彪,性能優(yōu)化