本節(jié)主要理解:
1.runloop的理解與介紹(相關類與mode)
2.runloop在開發(fā)中的應用(主動使用/隱性調用)
3.runloop與線程的關系
4.Runloop與NSTimer的關系
■應用范疇
口 定時器( Timer )、PerformSelector
口 GCD Async Main Queue
口 事件響應、手勢識別万栅、界面刷新
口 網絡請求
口 AutoreleasePool
偽代碼
int main (int argc ,char * argv[]) [
@autoreleasepool {
int retVal = 0;
do {
//睡眠中等待消息
int message = sleep_ and_ _wait();
//處理消息
retVal = process. _message (message) ;
} while (0 == retVal);
return 0;
}
}
一.runloop相關的類
Core Foundation關于RunLoop5↑類
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
他們之間的關系可以用下圖表示
■Source0
觸摸事件處理(事件響應)
口performSe lector: onThread :
Source0 只包含了一個回調(函數指針),它并不能主動觸發(fā)事件咕宿。使用時,你需要先調用 CFRunLoopSourceSignal(source)蜡秽,將這個 Source 標記為待處理府阀,然后手動調用 CFRunLoopWakeUp(runloop) 來喚醒 RunLoop,讓其處理這個事件芽突。
■Source1
口基于Port的線程間通信
口系統(tǒng)事件捕捉
Source1 包含了一個 mach_port 和一個回調(函數指針)试浙,被用于通過內核和其他線程相互發(fā)送消息。這種 Source 能主動喚醒 RunLoop 的線程寞蚌。
■Timers
口NSTimer
口perform Selector:with0bject :afterDelay:
■Observers
口用于監(jiān)聽RunLoop的狀態(tài)
口UI刷新( BeforeWaiting )
口 Autorelease pool ( BeforeWaiting )
二.RunloopMode
常見的2種Моdе
kCFRunLoopDefaultMode ( NSDefaultRunLoopMode ) : App的默認mode田巴,通常主線程是在這個mode下運行
UITrackingRunLoopMode :界面跟蹤mode,用于scrollview追蹤觸摸滾動挟秤,保證界面滑動時不受其他mode影響
當使用kCFRunLoopCommonModes模式監(jiān)聽runloop時壹哺,以上兩種模式都將被監(jiān)聽到
二.Runloop在實際開發(fā)中的應用
1.控制線程的生命周期(線程保活)-如AFNetworking
往runloop中添加Source/Timer/Observer
run方法時無法停止的艘刚,它專門用來開啟一個永不銷毀的線程
[NSRunloop currentrunloop] run];
2.解決NSTimer在滑動時停止工作的問題
NSTimer是由RunLoop來管理的管宵,NSTimer其實就是CFRunLoopTimerRef。
因為runloop只能運行在一種模式下,滾動時箩朴,會模式切換笛臣。
使用NSRunLoopCommonModes,會讓NSTimer在兩種模式下工作
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@"%d", ++count);
}];
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
// NSDefaultRunLoopMode隧饼、UITrackingRunLoopMode才是真正存在的模式
// NSRunLoopCommonModes并不是一個真的模式,它只是一個標記
// timer能在_commonModes數組中存放的模式下工作
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
3.監(jiān)控應用卡頓/性能優(yōu)化
可以添加Observer到主線程RunLoop中,通過監(jiān)聽RunLoop狀態(tài)切換的耗時,以達到監(jiān)控卡頓的目的
面試題
1.講講RunLoop, ,項目中有用到嗎?
-控制線程的生命周期/調度静陈,(線程毖嘌悖活/線程間通訊切換)
解決NSTimer在滾動時停止工作的問題
監(jiān)控應用卡頓
性能優(yōu)化
2.runloop內部實現(xiàn)邏輯 ?
實際上 RunLoop 就是這樣一個函數,其內部是一個 do-while 循環(huán)鲸拥。當你調用 CFRunLoopRun() 時拐格,線程就會一直停留在這個循環(huán)里;直到超時或被手動停止刑赶,該函數才會返回捏浊。
3.runloop和線程的關系 ?
一個線程對應一個runloop
線程在執(zhí)行完任務后,會處于休眠狀態(tài)撞叨,隨時等待接受新的任務金踪,而不是退出
只有主線程的RunLoop是默認開啟的,所以程序在開啟后牵敷,會一直運行胡岔,不會退出。其他線程的RunLoop如果需要開啟枷餐,就手動開啟
4.NSTimer 與runloop的關系?
1.NSTimer是由RunLoop來管理的靶瘸,NSTimer其實就是CFRunLoopTimerRef。
2.子線程中創(chuàng)建Timer要將其Runloop開啟[[NSRunLoop currentRunLoop]run];否則會不執(zhí)行Timer事件
5.程序中添加每3秒響應一 次的NSTimer ,當拖動tableview時timer可能無法響應要怎么解決?
NSTimer是由RunLoop來管理的毛肋,NSTimer其實就是CFRunLoopTimerRef怨咪。
因為runloop只能運行在一種模式下,滾動時润匙,會模式切換诗眨。
使用NSRunLoopCommonModes,會讓NSTimer在兩種模式下工作
6.runloop 是怎么響應用戶操作的趁桃,具體流程是什么樣的?
(簡介版:由source1接收事件辽话,由source0響應觸摸事件)
用戶交互事件首先在 IOHID 層生成 HIDEvent,然后向事件處理線程的 Source1 的 mach port 發(fā)送 HIDEvent 消息卫病,Source1 的回調函數將事件轉化為 UIEvent 并篩選需要處理的事件推入待處理事件隊列油啤,向主線程的事件處理 Source0 發(fā)送信號,并喚醒主線程蟀苛,主線程檢查到事件處理 Source0 有待處理信號后益咬,觸發(fā) Source0 的回調函數,從待處理事件隊列中提取 UIEvent帜平,最后進入 hit-test 等 UIEvent 事件響應流程幽告。
7.說說runLoop的幾種狀態(tài)
8.runloop的mode作用是什么 ?
model 主要是用來指定事件在運行循環(huán)中的優(yōu)先級的梅鹦,分為:
- NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默認,空閑狀態(tài)
- UITrackingRunLoopMode :ScrollView滑動時
- UIInitializationRunLoopMode :啟動時
- NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集
參考
runloop詳解