iOS RunLoop

深入理解RunLoop:http://www.cocoachina.com/ios/20150601/11970.html

iOS學(xué)習(xí)之RunLoop的深入理解:http://blog.csdn.net/zhonggaorong/article/details/52313740

課件:http://www.cnblogs.com/cqb-learner/p/5859431.html? ? http://www.cnblogs.com/cqb-learner/p/5860084.html

iOS Runloop學(xué)習(xí):http://www.cocoachina.com/ios/20160307/15590.html

iOS RunLoop的基本用法:http://blog.csdn.net/qcx321/article/details/53217502


RunLoop更強(qiáng)大的地方在于對(duì)消息的監(jiān)聽,因?yàn)镃FRunLoopRef的線程安全優(yōu)勢(shì),我們通常會(huì)更多使用后者。

細(xì)心的你可能會(huì)發(fā)現(xiàn)瑟啃,輸入源被注冊(cè)進(jìn)Runloop中時(shí)會(huì)有方法進(jìn)行remove,但是定時(shí)器卻沒有眼坏,但是定時(shí)器中的invalidate方法可以將其從runloop中移除沦童,正如官方文檔的說(shuō)明:invalidate是重要也是唯一的可以將定時(shí)器從runloop的注銷的方法境蜕,所以如果我們創(chuàng)建了定時(shí)器谊惭,就一定要在不使用時(shí)調(diào)用invalidate方法汽馋。我不知道apple為何將定時(shí)器的方法分離開來(lái)侮东,可能的原因是讓開發(fā)者更少的顯式調(diào)用runloop的方法圈盔,你若是知道原因,懇請(qǐng)留言指導(dǎo)悄雅。

一.RunLoop基本概念

概念:程序的運(yùn)行循環(huán),通俗的來(lái)說(shuō)就是跑圈.

1. 基本作用(作用重大)

(1) 保持程序的持續(xù)運(yùn)行(iOS程序?yàn)槭裁茨芤恢被钪粫?huì)死)

(2) 處理app中的各種事件(比如觸摸事件驱敲、定時(shí)器事件【NSTimer】、selector事件【選擇器·performSelector···】)

(3)節(jié)省CPU資源宽闲,提高程序性能众眨,有事情就做事情,沒事情就休息

2. 重要說(shuō)明

(1)如果沒有Runloop,那么程序一啟動(dòng)就會(huì)退出容诬,什么事情都做不了娩梨。

(2)如果有了Runloop,那么相當(dāng)于在內(nèi)部有一個(gè)死循環(huán)览徒,能夠保證程序的持續(xù)運(yùn)行

3.main函數(shù)中的Runloop

(1) 在UIApplication函數(shù)內(nèi)部就啟動(dòng)了一個(gè)Runloop,該函數(shù)返回一個(gè)int類型的值

(2) 這個(gè)默認(rèn)啟動(dòng)的Runloop是跟主線程相關(guān)聯(lián)的

4.Runloop對(duì)象

(1)在iOS開發(fā)中有兩套api來(lái)訪問(wèn)Runloop

第一種:foundation框架【NSRunloop】

第二種:core foundation框架【CFRunloopRef】

(2)NSRunLoop和CFRunLoopRef都代表著RunLoop對(duì)象,它們是等價(jià)的狈定,可以互相轉(zhuǎn)換

(3)NSRunLoop是基于CFRunLoopRef的一層OC包裝,所以要了解RunLoop內(nèi)部結(jié)構(gòu),需要多研究CFRunLoopRef層面的API(Core Foundation層面)

5.Runloop與線程

(1) Runloop和線程的關(guān)系:一個(gè)Runloop對(duì)應(yīng)著一條唯一的線程

問(wèn)題:如何讓子線程不死

回答:給這條子線程開啟一個(gè)Runloop

(2) Runloop的創(chuàng)建:主線程Runloop已經(jīng)創(chuàng)建好了纽什,子線程的runloop需要手動(dòng)創(chuàng)建

(3) Runloop的生命周期:在第一次獲取時(shí)創(chuàng)建措嵌,在線程結(jié)束時(shí)銷毀

(4) 拿到當(dāng)前應(yīng)用程序的主Runloop(主線程對(duì)應(yīng)的Runloop)

方法一: NSRunloop

NSRunLoop * runloop1=[NSRunLoop mainRunLoop];

方法二: CFRunLoopRef

CFRunLoopRef runloop2=CFRunLoopGetMain();

(5)注意點(diǎn):開一個(gè)子線程創(chuàng)建runloop,不是通過(guò)alloc init方法創(chuàng)建,而是直接通過(guò)調(diào)用currentRunLoop方法來(lái)創(chuàng)建芦缰,它本身是一個(gè)懶加載的企巢。

二.Runloop運(yùn)行原理

1.蘋果官方的運(yùn)行原理圖

2.Runloop和相關(guān)類之間的關(guān)系圖

RunLoop五個(gè)相關(guān)的類

CFRunloopRef

CFRunloopModeRef【Runloop的運(yùn)行模式】

CFRunloopSourceRef【Runloop要處理的事件源】

CFRunloopTimerRef【Timer事件】

CFRunloopObserverRef【Runloop的觀察者(監(jiān)聽者)】

以下是五個(gè)相關(guān)類的拋析:

CFRunloopRef

(1) CFRunloopModeRef代表著Runloop的運(yùn)行模式

(2) 一個(gè)Runloop中可以有多個(gè)mode,一個(gè)mode里面又可以有多個(gè)source\observer\timer等等

(3) 每次runloop啟動(dòng)的時(shí)候,只能指定一個(gè)mode,這個(gè)mode被稱為該Runloop的當(dāng)前mode

(4) 如果需要切換mode,只能先退出當(dāng)前Runloop,再重新指定一個(gè)mode進(jìn)入

(5) 這樣做主要是為了分割不同組的定時(shí)器等让蕾,讓他們相互之間不受影響

(6) 系統(tǒng)默認(rèn)注冊(cè)了5個(gè)mode

第一種模式: kCFRunLoopDefaultMode:App的默認(rèn)Mode浪规,通常主線程是在這個(gè)Mode下運(yùn)行

第二種模式: UITrackingRunLoopMode:界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動(dòng)探孝,保證界面滑動(dòng)時(shí)不受其他 Mode 影響

第三種模式: UIInitializationRunLoopMode: 在剛啟動(dòng) App 時(shí)第進(jìn)入的第一個(gè) Mode罗丰,啟動(dòng)完成后就不再使用

第四種模式: GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode,通常用不到

第五種模式: kCFRunLoopCommonModes: 這是一個(gè)占位用的Mode再姑,不是一種真正的Mode

CFRunloopTimerRef

(1) runloop一啟動(dòng)就會(huì)選中一種模式萌抵,當(dāng)選中了一種模式之后其它的模式就不會(huì)參與。一個(gè)mode里面可以添加多個(gè)NSTimer,也就是說(shuō)以后當(dāng)創(chuàng)建NSTimer的時(shí)候元镀,可以指定它是在什么模式下運(yùn)行的绍填。

(2) 它是基于時(shí)間的觸發(fā)器,說(shuō)直白點(diǎn)那就是時(shí)間到了我就觸發(fā)一個(gè)事件栖疑,觸發(fā)一個(gè)操作讨永。基本上說(shuō)的就是NSTimer .

(3) 相關(guān)代碼 / - (void)timer2 { //NSTimer 調(diào)用了scheduledTimer方法遇革,那么會(huì)自動(dòng)添加到當(dāng)前的runloop里面去卿闹,而且runloop的運(yùn)行模式kCFRunLoopDefaultMode

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0target:selfselector:@selector(run) userInfo:nilrepeats:YES];[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

CFRunloopSourceRef

(1)是事件源也就是輸入源,有兩種分類模式萝快;

一種是按照蘋果官方文檔進(jìn)行劃分的

另一種是基于函數(shù)的調(diào)用棧來(lái)進(jìn)行劃分的(source0和source1)锻霎。

(2)具體的分類情況

*以前的分法

Port-Based Sources

Custom Input Sources

Cocoa Perform Selector Sources

*現(xiàn)在的分法

Source0:非基于Port的

Source1:基于Port的

(3) 可以通過(guò)打斷點(diǎn)的方式查看一個(gè)方法的函數(shù)調(diào)用棧

CFRunLoopObserverRef

(1) CFRunLoopObserverRef是觀察者,能夠監(jiān)聽RunLoop的狀態(tài)改變

(2) 如何監(jiān)聽

//創(chuàng)建一個(gè)runloop監(jiān)聽者

CFRunLoopObserverRef observer =

CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(),kCFRunLoopAllActivities,

YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {

NSLog(@”監(jiān)聽runloop狀態(tài)改變—%zd”,activity); });

?//為runloop添加一個(gè)監(jiān)聽者?

CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer,

kCFRunLoopDefaultMode);?

CFRelease(observer);

(3)監(jiān)聽的狀態(tài)

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {

kCFRunLoopEntry = (1UL << 0), //即將進(jìn)入Runloop

kCFRunLoopBeforeTimers = (1UL << 1), //即將處理NSTimer

kCFRunLoopBeforeSources = (1UL << 2), //即將處理Sources

kCFRunLoopBeforeWaiting = (1UL << 5), //即將進(jìn)入休眠

kCFRunLoopAfterWaiting = (1UL << 6), //剛從休眠中喚醒

kCFRunLoopExit = (1UL << 7), //即將退出runloop

kCFRunLoopAllActivities = 0x0FFFFFFFU //所有狀態(tài)改變 };

三.RunLoop運(yùn)行邏輯

以下是網(wǎng)友整理的運(yùn)行邏輯圖:

通過(guò)上圖我們可以做以下運(yùn)行邏輯的總結(jié):

一個(gè)線程對(duì)應(yīng)一個(gè)runLoop,主線程的runloop是程序一啟動(dòng),默認(rèn)就創(chuàng)建一個(gè)runloop,創(chuàng)建好了之后就會(huì)給它添加一些默認(rèn)的模式,每個(gè)模式里面會(huì)有很多的 source /timer/observer ,添加好這些模式后,observer就會(huì)監(jiān)聽主線程的runloop,進(jìn)入runloop后,就開始處理事件,先處理timer,再處理source0,source0處理完之后再處理source1,當(dāng)把這些所有的事件反復(fù)的處理完之后,如果沒有事件了,那么runloop就會(huì)進(jìn)入睡眠狀態(tài),當(dāng)用戶又觸發(fā)了新的事件,就會(huì)喚醒runloop,喚醒runloop后回到第二步,重新處理新的timer,新的source0,新的source1,處理完后就睡眠,一直反復(fù),當(dāng)我們把程序關(guān)閉或者強(qiáng)退,這個(gè)時(shí)候observer就會(huì)監(jiān)聽都runloop退出了.

observer是監(jiān)聽runloop狀態(tài)的.

timer / source/

CFRunLoopRef創(chuàng)建一個(gè)timer必須添加到runloop 才會(huì)執(zhí)行,添加的時(shí)候要指定模式 defaurce模式 ,不對(duì)程序做任何操作 timer就會(huì)后臺(tái)運(yùn)行 ,當(dāng)我進(jìn)行操作的時(shí)候runloop模式就會(huì)從默認(rèn)模式切換到其他模式,假如說(shuō)我操作scrollerView 它就會(huì)從default模式切換到tracking模式

而roonloop 同一時(shí)刻只能執(zhí)行一種模式.

當(dāng)在創(chuàng)建timer時(shí)指定 Comment 僅僅是個(gè)標(biāo)記,默認(rèn)和追蹤,那么timer就會(huì)隨著觸發(fā)的模式不同進(jìn)行 默認(rèn)和追蹤模式的選擇

Source :source一般是不會(huì)去操作的,第一種是基于自定義的,第二種是基于端口的,第三種是基于Performselect的

通過(guò)函數(shù)調(diào)用棧來(lái)對(duì)source分類:分為source0 source1 :

source0是非基于端口的,是用戶自己手動(dòng)觸發(fā)的操作,比如觸摸滑動(dòng)等操作.

Source1是系統(tǒng)內(nèi)部的一些端口觸發(fā)的事件

子線程的runloop需要手動(dòng)創(chuàng)建,需要手動(dòng)開啟

5.自動(dòng)釋放池,什么時(shí)候創(chuàng)建和釋放 ?

(1)第一次創(chuàng)建:是在runloop進(jìn)入的時(shí)候創(chuàng)建 對(duì)應(yīng)的狀態(tài) = KCFRunLoopEntry

(2)最后一個(gè)退出,是在runloop退出的時(shí)候 對(duì)應(yīng)的狀態(tài) = KCFRunLoopExit

(3)其他的創(chuàng)建和釋放

每次睡覺的時(shí)候會(huì)釋放前自動(dòng)釋放池,再創(chuàng)建一個(gè)新的

即將進(jìn)入睡眠的時(shí)候,先釋放上一次創(chuàng)建的自動(dòng)釋放池,然后再創(chuàng)建一個(gè)新的釋放池

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揪漩,一起剝皮案震驚了整個(gè)濱河市旋恼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奄容,老刑警劉巖冰更,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昂勒,居然都是意外死亡蜀细,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門戈盈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奠衔,“玉大人,你說(shuō)我怎么就攤上這事』辆酰” “怎么了痴荐?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)官册。 經(jīng)常有香客問(wèn)我生兆,道長(zhǎng),這世上最難降的妖魔是什么膝宁? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任鸦难,我火速辦了婚禮,結(jié)果婚禮上员淫,老公的妹妹穿的比我還像新娘合蔽。我一直安慰自己,他們只是感情好介返,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布拴事。 她就那樣靜靜地躺著,像睡著了一般圣蝎。 火紅的嫁衣襯著肌膚如雪刃宵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天徘公,我揣著相機(jī)與錄音牲证,去河邊找鬼。 笑死关面,一個(gè)胖子當(dāng)著我的面吹牛坦袍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播等太,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捂齐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了澈驼?” 一聲冷哼從身側(cè)響起辛燥,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤筛武,失蹤者是張志新(化名)和其女友劉穎缝其,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徘六,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡内边,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了待锈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漠其。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出和屎,到底是詐尸還是另有隱情拴驮,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布柴信,位于F島的核電站套啤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏随常。R本人自食惡果不足惜潜沦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绪氛。 院中可真熱鬧唆鸡,春花似錦、人聲如沸枣察。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)序目。三九已至燃乍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宛琅,已是汗流浹背刻蟹。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嘿辟,地道東北人舆瘪。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像红伦,于是被迫代替她去往敵國(guó)和親英古。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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