NSRunloop簡單細(xì)說(六)—— 幾種循環(huán)模式詳細(xì)解析

版本記錄

版本號 時間
V1.0 2017.08.23

前言

NSRunloopOC Foundation框架中非常重要的一個類,很多時候我們會使用它,但是未必對其有深入的了解,接下來幾篇我就會帶著大家重新學(xué)習(xí)一下NSRunloop這個類,從簡單到復(fù)雜雄右,從基本到深化,我會一步步的走完纺讲。希望對大家有所幫助擂仍。感興趣的可以看我上一篇。
1. NSRunloop簡單細(xì)說(一)—— 整體了解
2. NSRunloop簡單細(xì)說(二)—— 獲取運(yùn)行循環(huán)及其模式
3. NSRunloop簡單細(xì)說(三)—— 定時器和端口
4. NSRunloop簡單細(xì)說(四)—— 開啟Runloop
5. NSRunloop簡單細(xì)說(五)—— 調(diào)度和取消消息

幾種循環(huán)模式簡介

關(guān)于循環(huán)模式可以參考文檔

運(yùn)行循環(huán)模式是要監(jiān)視的輸入源和定時源的集合熬甚,以及要通知的運(yùn)行循環(huán)觀察器的集合逢渔。 每次運(yùn)行運(yùn)行循環(huán)時,都可以指定(顯式地或隱式地)運(yùn)行一個特定的“模式”乡括。 在運(yùn)行循環(huán)的通過期間肃廓,僅監(jiān)視與該模式相關(guān)聯(lián)的源,并允許其傳遞其事件诲泌。 (同樣盲赊,只有與該模式關(guān)聯(lián)的觀察者才會被通知運(yùn)行循環(huán)的進(jìn)度。 與其他模式相關(guān)聯(lián)的源將持續(xù)到任何新事件敷扫,直到以適當(dāng)模式通過循環(huán)角钩。

在您的代碼中,您可以按名稱識別模式呻澜。CocoaCore Foundation都定義了默認(rèn)模式和幾種常用模式,以及用于在代碼中指定這些模式的字符串惨险。 您可以通過簡單地為模式名稱指定自定義字符串來定義自定義模式羹幸。 雖然您分配給自定義模式的名稱是任意的,但這些模式的內(nèi)容不是辫愉。 您必須確保將一個或多個輸入源栅受,計(jì)時器或運(yùn)行循環(huán)觀察器添加到您創(chuàng)建的任何模式,使其有用恭朗。

您可以使用模式在特定通過運(yùn)行循環(huán)的過程中過濾來自不需要的源的事件屏镊。 大多數(shù)情況下,您將要在系統(tǒng)定義的“默認(rèn)”模式下運(yùn)行運(yùn)行循環(huán)痰腮。 但是而芥,模態(tài)面板可能會以“模態(tài)”模式運(yùn)行。 在此模式下膀值,只有與模式面板相關(guān)的來源才會將事件傳遞給線程棍丐。 對于輔助線程误辑,可以使用自定義模式來防止低優(yōu)先級源在時間緊迫的操作期間傳遞事件。

這里還要注意:模式根據(jù)事件的來源進(jìn)行區(qū)分歌逢,而不是事件的類型巾钉。 例如,您不會使用模式僅匹配鼠標(biāo)向下事件或僅匹配鍵盤事件秘案。 您可以使用模式來監(jiān)聽不同的端口集砰苍,臨時暫停定時器,或以其他方式更改源和運(yùn)行當(dāng)前正在監(jiān)視的循環(huán)觀察器阱高。

其實(shí)前面我們都已經(jīng)簡要的說了一下NSRunloop的幾種循環(huán)模式了赚导,這一篇主要就是擴(kuò)展,詳細(xì)的說一下這幾種循環(huán)模式讨惩。

FOUNDATION_EXPORT NSRunLoopMode const NSDefaultRunLoopMode;
FOUNDATION_EXPORT NSRunLoopMode const NSRunLoopCommonModes NS_AVAILABLE(10_5, 2_0);
typedef NSString * NSRunLoopMode NS_EXTENSIBLE_STRING_ENUM;

系統(tǒng)為我們提供了多種模式辟癌,如下所示:

  • Default模式

  • Connection模式

    • 定義:NSConnectionReplyMode(Cocoa)描述:處理NSConnection對象相關(guān)事件荐捻,系統(tǒng)內(nèi)部使用黍少,用戶基本不會使用。
  • Modal模式

    • 定義:NSModalPanelRunLoopMode(Cocoa)描述:處理modal panels事件处面。
  • Event tracking模式

    • 定義:UITrackingRunLoopMode(iOS) NSEventTrackingRunLoopMode(cocoa)描述:在拖動loop或其他user interface tracking loops時處于此種模式下厂置,在此模式下會限制輸入事件的處理。例如魂角,當(dāng)手指按住UITableView拖動時就會處于此模式昵济。
  • Common模式

    • 定義:NSRunLoopCommonModes (Cocoa) kCFRunLoopCommonModes (Core Foundation)描述:這是一個偽模式,其為一組run loop mode的集合野揪,將輸入源加入此模式意味著在Common Modes中包含的所有模式下都可以處理访忿。在Cocoa應(yīng)用程序中,默認(rèn)情況下Common Modes包含default modes , modal modes ,event Tracking modes斯稳『C可使用CFRunLoopAddCommonMode方法想Common Modes中添加自定義modes。
幾種運(yùn)行模式

下面我們就詳細(xì)的研究一下這幾個運(yùn)行模式挣惰。


一卧斟、NSDefaultRunLoopMode

這個是默認(rèn)的運(yùn)行模式,也是最常用的運(yùn)行模式憎茂,NSTimerNSURLConnection默認(rèn)運(yùn)行該模式下珍语,所以如果我們不改變定時器的運(yùn)行模式,讓他在這個模式下運(yùn)行竖幔,那么當(dāng)我們拖動控件的時候板乙,變?yōu)?code>UITrackingRunLoopMode模式時,NSTimer就不能響應(yīng)了拳氢,解決方法就是將定時器加入到UITrackingRunLoopModeNSRunLoopCommonModes亡驰。另外晓猛,還有一種方法就是:將 Timer 加入到頂層的 RunLoopcommonModeItems 中。commonModeItems被 RunLoop 自動更新到所有具有Common屬性的 Mode 里去凡辱。

默認(rèn)模式是用于大多數(shù)操作的模式戒职。 大多數(shù)情況下,您應(yīng)該使用此模式啟動運(yùn)行循環(huán)并配置輸入源透乾。一般用于處理NSConnection對象以外的輸入源的模式


二洪燥、NSConnectionReplyMode

Cocoa將此模式與NSConnection對象結(jié)合使用來監(jiān)視回復(fù)。 你很少需要自己使用這種模式乳乌。


三捧韵、NSModalPanelRunLoopMode

Cocoa使用此模式來識別用于模式面板的事件。


四汉操、UITrackingRunLoopMode

Cocoa使用此模式在鼠標(biāo)拖動循環(huán)和其他類型的用戶界面跟蹤循環(huán)期間限制傳入事件再来。


五、NSRunLoopCommonModes

這是一組可配置的常用模式磷瘤。 將輸入源與此模式相關(guān)聯(lián)還將其與組中的每種模式相關(guān)聯(lián)芒篷。 對于Cocoa應(yīng)用程序,默認(rèn)情況下采缚,此設(shè)置包括default, modal, 和event tracking针炉。 Core Foundation最初只包含默認(rèn)模式。 您可以使用CFRunLoopAddCommonMode函數(shù)向該集合添加自定義模式扳抽。

主線程的 RunLoop 里有兩個預(yù)置的 Mode:kCFRunLoopDefaultModeUITrackingRunLoopMode篡帕。這兩個 Mode 都已經(jīng)被標(biāo)記為”Common”屬性。

這里還要說一下底層的東西贸呢,CFRunLoopMode镰烧,這個是NSRunLoopMode在C語言的底層,是一個結(jié)構(gòu)體楞陷,如下所示怔鳖。

struct __CFRunLoopMode {
    CFStringRef _name;            // Mode Name, 例如 @"kCFRunLoopDefaultMode"
    CFMutableSetRef _sources0;    // Set
    CFMutableSetRef _sources1;    // Set
    CFMutableArrayRef _observers; // Array
    CFMutableArrayRef _timers;    // Array
    ...
};

下面也順便看一下NSRunLoop的C語言底層。

struct __CFRunLoop {
    CFMutableSetRef _commonModes;     // Set
    CFMutableSetRef _commonModeItems; // Set<Source/Observer/Timer>
    CFRunLoopModeRef _currentMode;    // Current Runloop Mode
    CFMutableSetRef _modes;           // Set
    ...
};

這里有個概念叫 CommonModes:一個 Mode 可以將自己標(biāo)記為Common屬性(通過將其 ModeName 添加到 RunLoop 的 “commonModes” 中)猜谚。每當(dāng) RunLoop 的內(nèi)容發(fā)生變化時,RunLoop 都會自動將 _commonModeItems 里的 Source/Observer/Timer 同步到具有 “Common” 標(biāo)記的所有Mode里赌渣。

CFRunLoop對外暴露的管理 Mode 接口只有下面2個:

CFRunLoopAddCommonMode(CFRunLoopRef runloop, CFStringRef modeName);
CFRunLoopRunInMode(CFStringRef modeName, ...);

Mode 暴露的管理 mode item 的接口有下面幾個:

CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef modeName);
CFRunLoopAddObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef modeName);
CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef timer, CFStringRef mode);
CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef modeName);
CFRunLoopRemoveObserver(CFRunLoopRef rl, CFRunLoopObserverRef observer, CFStringRef modeName);
CFRunLoopRemoveTimer(CFRunLoopRef rl, CFRunLoopTimerRef timer, CFStringRef mode);

你只能通過 modeName 來操作內(nèi)部的 mode魏铅,當(dāng)你傳入一個新的modeName 但 RunLoop 內(nèi)部沒有對應(yīng) mode 時,RunLoop會自動幫你創(chuàng)建對應(yīng)的 CFRunLoopModeRef坚芜。對于一個 RunLoop 來說览芳,其內(nèi)部的 mode 只能增加不能刪除。

參考文章

1. iOS中NSRunLoop的模式
2. 深入理解RunLoop

后記

未完鸿竖,待續(xù)~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沧竟,一起剝皮案震驚了整個濱河市铸敏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悟泵,老刑警劉巖杈笔,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糕非,居然都是意外死亡蒙具,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門朽肥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來禁筏,“玉大人,你說我怎么就攤上這事衡招±槲簦” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵始腾,是天一觀的道長州刽。 經(jīng)常有香客問我,道長窘茁,這世上最難降的妖魔是什么怀伦? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮山林,結(jié)果婚禮上房待,老公的妹妹穿的比我還像新娘。我一直安慰自己驼抹,他們只是感情好桑孩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著框冀,像睡著了一般流椒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上明也,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天宣虾,我揣著相機(jī)與錄音,去河邊找鬼温数。 笑死绣硝,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的撑刺。 我是一名探鬼主播鹉胖,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了甫菠?” 一聲冷哼從身側(cè)響起挠铲,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寂诱,沒想到半個月后拂苹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刹衫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年醋寝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片带迟。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡音羞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仓犬,到底是詐尸還是另有隱情嗅绰,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布搀继,位于F島的核電站窘面,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏叽躯。R本人自食惡果不足惜财边,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望点骑。 院中可真熱鬧酣难,春花似錦、人聲如沸黑滴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽袁辈。三九已至菜谣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晚缩,已是汗流浹背尾膊。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荞彼,地道東北人冈敛。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像卿泽,于是被迫代替她去往敵國和親莺债。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

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