運行循環是什么?從介紹到演示

今天整理一下運行循環來幫朋友們了解一下什么是運行循環,也叫消息循環,建議大家稱之為運行循環(Runloop).


===

關于多線程的運行循環(消息循環)

1. 什么是運行循環

(1)Runloop就是運行循環,每個線程內部都有一個運行循環.

(2)只有主線程的運行循環默認是開啟的,子線程的運行循環.

2. 運行循環的作用

(1)保證程序不退出,iOS的應用程序啟動之后,之所以不會退出,就是因為有Runloop(運行循環).運行循環是一個死循環,只有滿足一定條件才會結束循環.

(2)負責處理輸入事件

(3)如果沒有事件發生,會讓程序進入休眠狀態.

3.輸入事件

Runloop接收的事件來自兩種不同的來源:輸入源 和 定時源.

(1)輸入源(Input sources)輸入源傳遞異步事件,通常消息來自于其他線程或程序。

(2)定時源(Timer sounces)定時源則傳遞同步事件,發生在特定時間或者重復的時間間隔。兩種源都使用程序的某一特定的處理例程來處理到達的事件。

(3)下圖展示了運行循環的概念結構以及事件來源的種類:
輸入源能夠通過runUntilDate 方法使線程退出;定時源不能使線程退出.

runloop.png

4.運行循環的模式

運行循環模式是輸入源和定時源的一個集合,這個集合會被監聽.

每次啟動運行循環,可以指定一個特殊的模式,在運行循環執行期間,只有跟特定的模式相關聯的事件源才會被監聽以及允許傳遞它們的事件。跟其它模式相關聯的事件源將不會被監聽。因此,可以通過運行循環來過濾掉一些不期望的事件

下圖是系統定義的幾種運行循環模式:

Mode Name Description
Default NSDefaultRunLoopMode(Cocoa)kCFRunLoopDefaultMode (Core Foundation) The default mode is the one used for most operations. Most of the time, you should use this mode to start your run loop and configure your input sources.
Connection NSConnectionReplyMode(Cocoa) Cocoa uses this mode in conjunction with NSConnection objects to monitor replies. You should rarely need to use this mode yourself
Modal NSModalPanelRunLoopMode(Cocoa) Cocoa uses this mode to identify events intended for modal panels.
Event tracking NSEventTrackingRunLoopMode(Cocoa) Cocoa uses this mode to restrict incoming events during mouse-dragging loops and other sorts of user interface tracking loops.
Common modes NSRunLoopCommonModes(Cocoa)kCFRunLoopCommonModes (Core Foundation) This is a configurable group of commonly used modes. Associating an input source with this mode also associates it with each of the modes in the group. For Cocoa applications, this set includes the default, modal, and event tracking modes by default. Core Foundation includes just the default mode initially. You can add custom modes to the set using theCFRunLoopAddCommonMode function.

大致的意思是指:

(1)Default: default模式可以用于大多數操作。在大多數時間,應該使用這種模式來啟動和設置輸入源。

(2)Connection: Cocoa使用這種模式聯合NSConnection對象來監聽響應。我們很少會自己用到這種模式

(3)Modal: Cocoa使用這種模式來識別為模態面板準備的事件。

(4)Event tracking: Cocoa使用這種模式來約束鼠標拖拽或其它用戶界面追蹤循環的事件。

(5)Common modes: 這是一個通用的模式組,使用這種模式關聯輸入源,同樣會關聯這個模式組里面的每一種模式。對于Cocoa應用來說,這個集合包含了 default、modal以及event tracking模式。
Core Foundation初始狀態下只包含 default 模式,但是可以
通過 CFRunLoopAddCommonMode函數來添加自定義模式。

5.通過定時器演示運行循環的模式

注意:定時器執行的方法中不宜執行太耗時的操作,否則會降低用戶體驗.

  • 第一步:創建定時器
    在viewDidLoad方法中:
//1,創建定時器
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:
self selector:@selector(demo) userInfo:nil repeats:YES]; 
//demo方法
- (void)demo {
        NSLog(@"hello");
}
  • 第二步:將定時器添加到當前線程的運行循環
//將定時器添加到當前線程的運行循環
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

===

注意:這里的模式對應的是輸入事件(定時器timer)的模式.

  • 第三步:運行程序,執行結果如下:
屏幕快照 2016-03-12 下午9.54.24.png
當程序運行起來之后,打印輸出會按照定時器,每秒輸出一次.但是,如果拖動界面的控件,打印輸出就會停止(即不再打印輸出).
思考:為什么?
  • 第四步: 打印當前運行循環的模式

demo方法中:

NSLog(@"---%@", [NSRunLoop currentRunLoop].currentMode);

執行程序:

屏幕快照 2016-03-12 下午9.58.52.png

注意:[NSRunLoop currentRunLoop].currentMode 中的模式對應的是運行循環的模式。

結論:
運行循環是在一個指定的模式下運行的(默認是NSDefaultRunLoopMode),設置的輸入事件也需要指定一個模式,運行循環的模式必須和輸入事件的模式相匹配才會執行。
一開始,輸入事件模式是NSDefaultRunLoopMode,運行循環默認也是NSDefaultRunLoopMode,所以可以正常輸出結果。
拖動控件,之所以不會打印輸出,就是因為運行循環的模式發生了改變,變成了 UITrackingRunLoopMode,這個時候二者模式不匹配,所以不能正常輸出。

總結:

(1)運行循環是在一個指定的模式下運行的,輸入事件也有對應的模式,只有當二者的模式相匹配,對應的方法才會執行。

(2)運行循環模式:
1> 運行循環啟動后,默認模式為 NSRunLoopDefaultMode
2> 如果滾動scrollView,運行循環模式為 UITrackingRunLoopMode。

子線程的運行循環

主線程的運行循環默認是開啟的,子線程的運行循環默認是不開啟的。
//第一步: 創建子線程
viewDidLoad方法中: 
    // 創建子線程
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];
    [thread start];
//第二步: 往子線程的運行循環添加輸入源
// 往子線程的運行循環上添加輸入源
    [self performSelector:@selector(demo1) onThread:thread withObject:
nil waitUntilDone:NO];
// 執行在子線程的方法
- (void)demo {
     NSLog(@"I'm running");
}
// 執行在子線程的運行循環中的方法
- (void)demo1 {
-   NSLog(@"I'm running on runloop");
}
第三步: 開啟子線程的運行循環
- (void)demo {
    NSLog(@"I'm running");
    // 這些數入源能夠防止運行循環退出, 即 只要有數入源, run 方法啟動的運行循環就不會退出
    // Those sources could therefore prevent the run loop from exiting.
[[NSRunLoop currentRunLoop] run];
NSLog(@"end");
}
然后執行程序得到以下結果:

屏幕快照 2016-03-12 下午10.05.45.png

由輸出結果可知: 沒有打印 end,即只要有輸入源,使用run方法啟動的運行循環不會退出。

第五步: 通過 runUntilDate來啟動運行循環

// 2秒鐘之后消息循環結束

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];

這樣的話,2秒鐘之后,子線程的運行循環就會退出。

希望能幫到大家!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容