什么是NSRunLoop

什么是Runloop?

RunLoop是一個事件處理循環(huán),是一種讓線程能隨時處理事件但不退出的機(jī)制公壤。它的目的是為了讓線程在有消息到來時能夠被立即喚醒執(zhí)行任務(wù)鞠呈,在沒有消息使能夠使線程休眠避免資源占用。
一般來講帆疟,一個線程一次只能執(zhí)行一個任務(wù),執(zhí)行完成后線程就會退出宇立。Event Loop模型提供了一個機(jī)制踪宠,讓線程能隨時處理事件但并不退出,他的代碼邏輯大概是這樣的:

function loop() {
    initialize();
    do {
        var message = get_next_message();
        process_message(message);
    } while (message != quit);
}

NSRunLoop是對Event Loop模型的一種具體實(shí)現(xiàn)妈嘹。

運(yùn)行循環(huán)從兩種不同類型的源接收事件柳琢。輸入源提供異步事件,通常是來自另一個線程或來自不同應(yīng)用程序的消息润脸。定時器源提供在指定時間執(zhí)行或指定時間間隔重復(fù)執(zhí)行的同步事件柬脸。兩種類型的源都使用特定于應(yīng)用程序的處理程序例程來處理事件。

Run Loop Modes

一個run loop mode就是input sources(Port-Based Sources毙驯、Custom Input Sources倒堕、Cocoa Perform Selector Sources)、Timers和該run loop所有的監(jiān)聽者(observers)的集合爆价。每次執(zhí)行run loop都需要指定一個mode涩馆。不同mode通過名稱區(qū)分。
Cocoa和Core Foundation都定義了默認(rèn)模式和幾種常用模式允坚,以及用于在代碼中指定這些模式的字符串。您只需為模式名稱指定自定義字符串即可定義自定義模式蛾号。
Foundation框架常用的mode有以下幾種:

  1. NSDefaultRunLoopMode
    會經(jīng)常使用,默認(rèn)模式是用于大多數(shù)操作的模式稠项。大多數(shù)情況下,您應(yīng)該使用此模式啟動運(yùn)行循環(huán)并配置輸入源鲜结。

  2. NSEventTrackingRunLoopMode
    使用此模式在鼠標(biāo)拖動循環(huán)和其他種類的用戶界面跟蹤循環(huán)期間限制傳入事件展运。

  3. NSModalPanelRunLoopMode
    A run loop should be set to this mode when waiting for input from a modal panel, such as NSSavePanel or NSOpenPanel.

  4. UITrackingRunLoopMode
    The mode set while tracking in controls takes place. You can use this mode to add timers that fire during tracking.
    在控件中觸發(fā)用戶界面跟蹤時使用該模式. 可以用該模式添加需要在用戶界面跟蹤起價執(zhí)行的timer.

  5. NSRunLoopCommonModes
    會經(jīng)常使用,這是一組可配置的常用模式精刷。將輸入源與此模式相關(guān)聯(lián)也會將其與組中的每個模式相關(guān)聯(lián)拗胜。也就是說,關(guān)聯(lián)到這個模式的事件或輸入源會自動關(guān)聯(lián)到這個組下面其他的模式怒允。
    對于Foundation應(yīng)用程序埂软,此集合默認(rèn)包括NSDefaultRunLoopMode,NSModalPanelRunLoopMode和NSEventTrackingRunLoopMode纫事。UITrackingRunLoopMode在Threading Programming Guide中沒有說明勘畔,但是在NSRunLoopMode的Reference中有說明所灸,不確定是否包含。
    這也就是為什么炫七,當(dāng)我們需要添加一個可以在UIScrollView滑動時也可以執(zhí)行的timer時爬立,需要將timer添加到NSRunLoopCommonModes的RunLoop。因?yàn)楫?dāng)我們滑動UIScrollView時万哪,RunLoop會切換到NSEventTrackingRunLoopMode執(zhí)行侠驯,將timer添加到NSRunLoopCommonModes模式的RunLoop時,會自動把這個timer添加到這個組下面其他的模式奕巍。

Input Sources

輸入源一般有兩種吟策,一種是基于端口的輸入源,監(jiān)聽?wèi)?yīng)用程序的Mach端口傳遞的事件伍绳,操作系統(tǒng)內(nèi)核會自動發(fā)送信號踊挠。一種是自定義輸入源,監(jiān)聽自定義源的事件冲杀,需要從其他線程手動發(fā)送信號效床。

Port-Based Sources

Cocoa和Core Foundation框架對使用端口對象和函數(shù)創(chuàng)建基于端口的輸入源提供了內(nèi)建支持。你不需要直接去創(chuàng)建輸入源权谁,而是通過創(chuàng)建一個NSPort對象并使用NSPort對象的方法將端口添加到run loop剩檀。NSPort對象會幫你處理輸入源需要的創(chuàng)建和配置工作。

Custom Input Sources

自定義輸入源旺芽,除了要定義事件到達(dá)之后的行為沪猴,還需要自己定義事件傳遞機(jī)制。

Cocoa Perform Selector Sources

除了基于端口的源采章,Cocoa還定義了一個自定義輸入源用于在任何線程執(zhí)行選擇器运嗜。與基于端口的源不同,執(zhí)行選擇器源會在執(zhí)行完他的選擇器之后把自身從run loop中移除悯舟。
當(dāng)你在其他線程執(zhí)行一個選擇器時担租,目標(biāo)線程必須有一個活動的run loop,這對于你自己創(chuàng)建的線程來說抵怎,意味著你必須在代碼里面顯示的開啟了run loop之后才會執(zhí)行選擇器奋救。添加到主線程的選擇器會被立即執(zhí)行,是因?yàn)閼?yīng)用程序啟動時主線程已經(jīng)默認(rèn)創(chuàng)了一個活動的run loop反惕。

下表是定義在NSObject對象中可以在線程中執(zhí)行/取消執(zhí)行選擇器的方法:
Timer Sources

定時器源傳遞同步事件尝艘,用于通知線程在指定的時間去處理響應(yīng)的事情。定時器需要跟指定的mode關(guān)聯(lián)姿染,如果定時器沒有在當(dāng)前正在執(zhí)行的mode中背亥,那么它并不會被觸發(fā)。定時器源并不是實(shí)時的,它可能存在延遲隘梨。

Run Loop Observers

run loop會在執(zhí)行過程中的特定時間想觀察者發(fā)送消息程癌。這些時間點(diǎn)包括:

  • The entrance to the run loop.
  • When the run loop is about to process a timer.
  • When the run loop is about to process an input source.
  • When the run loop is about to go to sleep.
  • When the run loop has woken up, but before it has processed the event that woke it up.
  • The exit from the run loop.
    可以使用Core Foundation框架中的CFRunLoopObserverRef對象向run loop注冊觀察者。

RunLoop與線程

1.每條線程都有唯一的與之對應(yīng)的RunLoop對象轴猎。
2.主線程的RunLoop已經(jīng)創(chuàng)建好了嵌莉,而子線程的需要手動創(chuàng)建。(也就是說子線程的RunLoop默認(rèn)是關(guān)閉的捻脖,因?yàn)橛袝r候開了個線程但卻沒有必要開一個RunLoop锐峭。 )
3.RunLoop在第一次獲取時創(chuàng)建,在線程結(jié)束時銷毀可婶。

References & Acknowledgements

官方文檔
深入理解RunLoop

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沿癞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子矛渴,更是在濱河造成了極大的恐慌椎扬,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件具温,死亡現(xiàn)場離奇詭異蚕涤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铣猩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門揖铜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人达皿,你說我怎么就攤上這事天吓。” “怎么了峦椰?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵龄寞,是天一觀的道長。 經(jīng)常有香客問我汤功,道長萄焦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任冤竹,我火速辦了婚禮,結(jié)果婚禮上茬射,老公的妹妹穿的比我還像新娘鹦蠕。我一直安慰自己,他們只是感情好在抛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布钟病。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肠阱。 梳的紋絲不亂的頭發(fā)上票唆,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機(jī)與錄音屹徘,去河邊找鬼走趋。 笑死,一個胖子當(dāng)著我的面吹牛噪伊,可吹牛的內(nèi)容都是我干的簿煌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鉴吹,長吁一口氣:“原來是場噩夢啊……” “哼姨伟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起豆励,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤夺荒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后良蒸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體技扼,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年诚啃,在試婚紗的時候發(fā)現(xiàn)自己被綠了淮摔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡始赎,死狀恐怖和橙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情造垛,我是刑警寧澤魔招,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站五辽,受9級特大地震影響办斑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜杆逗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一乡翅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罪郊,春花似錦蠕蚜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腺毫。三九已至,卻和暖如春挣柬,著一層夾襖步出監(jiān)牢的瞬間潮酒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工邪蛔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留急黎,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓店溢,卻偏偏與公主長得像叁熔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子床牧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容