
Run Loop 是與進(jìn)程相關(guān)的基礎(chǔ)設(shè)施。Run Loop 是來(lái)協(xié)調(diào)待接受的事件、安排調(diào)度的,事件處理循環(huán)。Run Loop 的作用就是,有任務(wù),開(kāi)起進(jìn)程,沒(méi)任務(wù),休眠進(jìn)程。
翻譯自蘋(píng)果的 runloop 文檔
上一段代碼 ,與 NSRunLoop 和 NSThread 相關(guān),
NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];
-(void) someMethod
{
NSLog(@"operation");
}
Run Loop 是處理 sockets 網(wǎng)絡(luò), ports 端口, files 文件 , keyboard 鍵盤(pán) , mouse 鼠標(biāo) , timers 計(jì)時(shí)器 的機(jī)制的一層抽象。
NSThread 都有著專屬的 Run Loop ,可以通過(guò) currentRunLoop 方法訪問(wèn)。
一般是不需要直接訪問(wèn) Run Loop 的??梢杂镁W(wǎng)絡(luò)相關(guān)的組件指定Run Loop , 處理 IO 輸入輸出。
等著輸入源有數(shù)據(jù) / 事件,給定線程的 Run Loop 就會(huì)讓合適的輸入處理函數(shù)處理有數(shù)據(jù) / 事件,等待執(zhí)行的輸入源。
執(zhí)行完后,Run Loop 會(huì)還原。如果有其他輸入源的數(shù)據(jù) / 事件, 該線程的 Run Loop 會(huì)處理;如果無(wú), 該線程會(huì)進(jìn)入休眠狀態(tài)。
以上是抽象后的簡(jiǎn)單描述,省略了很多細(xì)節(jié)。
繼續(xù)解釋:
run loop 是不是只能在線程內(nèi)部訪問(wèn),執(zhí)行?
是的。 NSRunLoop 不是線程安全的。所以只在跑這個(gè) run loop 的線程的上下文中獲取比較好。
來(lái)一個(gè)簡(jiǎn)單地給 run loop 添加事件的例子?
上 ?? :
如果想要監(jiān)聽(tīng) port , 添加該 port 到 run loop 就可以了,這個(gè) run loop 就會(huì)監(jiān)聽(tīng)該 port 的活動(dòng),
- (void)addPort:(NSPort *)aPort forMode:(NSString *)mode
也可以直接給 run loop 添加計(jì)時(shí)器,
- (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode
Run Loop 會(huì)還原,什么意思?
每一次迭代中,run loop 會(huì)按照他的 mode ,處理所有的條件滿足的事件。這個(gè)問(wèn)題與 run loop 的 mode 相關(guān),要看文檔。
開(kāi)線程的時(shí)候,Run Loop 沒(méi)有被喚醒?
大多應(yīng)用,主線程的 Run Loop 自動(dòng)去跑。
人為開(kāi)的線程,要去開(kāi)啟對(duì)應(yīng)的 Run Loop ,響應(yīng)傳入的事件。
{
所以, 開(kāi)線程,用 timer ,需要手動(dòng)開(kāi)啟對(duì)應(yīng)的 Run Loop
}
能不能在線程外,給線程的 Run Loop 添加事件?
什么意思哈?
不是給 Run Loop 添加事件。是在持有 Run Loop 的線程中,添加輸入源,例如計(jì)時(shí)器事件源。該 Run Loop 就會(huì)監(jiān)聽(tīng)事件源的活動(dòng)。
輸入的數(shù)據(jù)可以來(lái)自其他的線程 / 進(jìn)程。處理輸入的 Run Loop 是監(jiān)聽(tīng)這些事件源的 Run Loop ,跑在線程上。
是不是,有時(shí)候可以用 Run Loop 堵塞線程一會(huì)?
是的。事件處理返回前, Run Loop 會(huì)駐留處理事件。任意 app 中,都會(huì)輕易發(fā)現(xiàn)這點(diǎn)。任意的IO操作中,例如點(diǎn)擊按鈕,加一個(gè)睡眠函數(shù)。方法完成了,主 Run Loop 就被阻塞了,整個(gè) UI 都掛了。
任何的 Run Loop 中,都適用。
Run, RunLoop, Run! RunLoop , 跑起來(lái)
交互性的應(yīng)用與命令行程序的區(qū)別,就是 RunLoop . 使用命令行程序, 先配參數(shù)開(kāi)起,執(zhí)行命令,就結(jié)束了。交互性的應(yīng)用等待用戶輸入,給用戶反饋,然后一直等。很多長(zhǎng)周期的進(jìn)程中,都有這種機(jī)制。舉個(gè)經(jīng)典的例子,服務(wù)端中的
while( 1 ){ select( ); }
...
CFRunLoop 中最重要的特性是 CFRunLoopModes , RunLoop 的模態(tài)。 RunLoop 處理 Run Loop Sources , Run Loop 的事件源。事件源登記在 Run Loop 的一到多個(gè)模態(tài)上。 Run Loop 必須在一個(gè)給定模態(tài)上跑。事件源新加了事件,只要當(dāng)該事件源與Run Loop 當(dāng)前的模態(tài)一致,Run Loop 才處理該事件。
Mode 分為不同的模式, Common, UITracking ... , 也是一種狀態(tài)。 個(gè)人覺(jué)得,可以叫模態(tài)。
建議閱讀 Run Loop 文檔,https://developer.apple.com/documentation/foundation/nsrunloop
線程中 Run Loop 的應(yīng)用,
說(shuō)明: 為了有意思一些, 我采取了意譯。
本文翻譯自
Stack Over Flow Understanding NSRunLoop
蘋(píng)果的 runloop 文檔