聊聊 iOS 中的 RunLoop 考題 (中文版)

Run (跑) Loop (圈)

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)用,

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1


說(shuō)明: 為了有意思一些, 我采取了意譯。

本文翻譯自

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容