iOS RunLoop(一)

級(jí)別: ★★☆☆☆
標(biāo)簽:「iOS」「RunLoop」「線程常駐」
作者: 陳彬
審校: QiShare團(tuán)隊(duì)

前言:
這篇文章主要內(nèi)容是介紹RunLoop的一些概念以及用法:使用RunLoop創(chuàng)建常駐線程埂软、自定義輸入源進(jìn)行線程通信等包警。同時(shí)借此機(jī)會(huì)希望能夠和大家一起討論RunLoop相關(guān)的知識(shí),加深對(duì)RunLoop的理解礁蔗。

一壤短、RunLoop是什么魔熏?

RunLoop是與線程相關(guān)的基礎(chǔ)架構(gòu)中的一部分衷咽,它是一個(gè)處理事件的循環(huán)(線程進(jìn)入這個(gè)循環(huán),運(yùn)行事件處理程序來(lái)響應(yīng)傳入的事件)蒜绽,RunLoop的目的是當(dāng)有事件需要處理時(shí)镶骗,線程是活躍的、忙碌的躲雅,當(dāng)沒有事件后鼎姊,線程進(jìn)入休眠。

RunLoop結(jié)構(gòu)以及事件來(lái)源:

一個(gè)RunLoop包含若干個(gè)Mode相赁,每個(gè)Mode包含若干個(gè)Source/Timer/Observer/Port相寇。當(dāng)啟動(dòng)一個(gè)RunLoop時(shí)會(huì)先指定一個(gè)Mode,檢查指定Mode是否存在以及Mode中是否含有SourceTimer钮科,如果Mode不存在或者Mode中無(wú)SourceTimer唤衫,認(rèn)為該Mode是一個(gè)空的ModeRunLoop就直接退出绵脯。

Input Source:
  • Port-Based Sources:監(jiān)聽AppMach Port佳励,由內(nèi)核發(fā)出信號(hào),輸入源收到信號(hào)后蛆挫,執(zhí)行相關(guān)的例程赃承。

  • Custom Input Sources:監(jiān)聽自定義的輸入源,需要在其它線程手動(dòng)發(fā)送信號(hào)悴侵,輸入源收到信號(hào)后瞧剖,執(zhí)行相關(guān)的例程。

  • Cocoa Perform Selector Sources:Cocoa中自定義的輸入源可免,目的是在不同線程中執(zhí)行任務(wù)抓于,同一線程中的任務(wù)是順序執(zhí)行的,當(dāng)任務(wù)執(zhí)行完成后系統(tǒng)會(huì)自動(dòng)移除這個(gè)源。(注意:在目標(biāo)線程中執(zhí)行任務(wù)時(shí)浇借,這個(gè)目標(biāo)線程必須有活躍的RunLoop

Timer Source:

時(shí)間源會(huì)在預(yù)設(shè)的時(shí)間同步傳遞事件給對(duì)應(yīng)的線程捉撮,計(jì)時(shí)器是線程通知自己做某事的一種方式。

計(jì)時(shí)器并不是真正的實(shí)時(shí)的逮刨,當(dāng)計(jì)時(shí)器未處于RunLoop當(dāng)前監(jiān)聽的Mode,那么計(jì)時(shí)器是不會(huì)計(jì)時(shí)調(diào)度任務(wù)的堵泽,只有RunLoop當(dāng)前監(jiān)聽的Mode是計(jì)時(shí)器關(guān)聯(lián)的Mode時(shí)修己,計(jì)時(shí)器才會(huì)開始執(zhí)行任務(wù),例如:NSTimer添加至主線程RunLoopDefaultMode中迎罗,此時(shí)滑動(dòng)TableView/ScrollView時(shí)睬愤,RunLoop會(huì)切換至TrackMode,計(jì)時(shí)器是不會(huì)調(diào)度任務(wù)的纹安。

如果RunLoop在執(zhí)行一個(gè)例程時(shí)尤辱,計(jì)時(shí)器觸發(fā)了砂豌,那么計(jì)時(shí)器會(huì)等待RunLoop將該例程執(zhí)行完成,在下一次的循環(huán)中處理光督。在RunLoop未運(yùn)行情況下阳距,計(jì)時(shí)器永遠(yuǎn)不會(huì)觸發(fā)任務(wù)。

二结借、RunLoop怎么使用筐摘?

應(yīng)用啟動(dòng)時(shí),會(huì)自動(dòng)在主線程上設(shè)置運(yùn)行RunLoop船老,所以不需要在主線程上顯示的啟動(dòng)RunLoop咖熟,無(wú)需調(diào)用[[NSRunLoop currentRunLoop] runUntilDate:]這些方法。那么如果我們顯示的在主線程中調(diào)用RunLooprun方法會(huì)出現(xiàn)什么結(jié)果呢柳畔?通過(guò)Demo中顯示馍管,主線程中顯示啟動(dòng)RunLoop會(huì)影響當(dāng)前事件處理,但是由于RunLoop并沒有停止薪韩,所以其他事件能夠正常接收和處理确沸。

而子線程也不并是必須要設(shè)置運(yùn)行RunLoop才能執(zhí)行任務(wù),比如說(shuō)只是簡(jiǎn)單在子線程中處理個(gè)耗時(shí)任務(wù)等躬存,如下場(chǎng)景是需要啟動(dòng)RunLoop的:

  1. 使用NSPort或者自定義輸入源與其它線程通信张惹。
  2. 在線程上使用計(jì)時(shí)器。
  3. 在一個(gè)Cocoa應(yīng)用中使用performSelector相關(guān)方法岭洲。
  4. 使線程常駐宛逗,在該線程定期執(zhí)行任務(wù)。

正如前言中所說(shuō)盾剩,本文主要說(shuō)明線程常駐和自定義輸入源線程通信雷激。

線程常駐:

方式一:無(wú)條件的啟動(dòng)RunLoop是最簡(jiǎn)單的選擇,但它也是最不可取的選擇告私,它會(huì)將線程置于永久循環(huán)中屎暇,這樣幾乎無(wú)法控制RunLoop本身,雖然可以添加和刪除輸入源和計(jì)時(shí)器驻粟,但停止RunLoop的唯一方法是殺死RunLoop根悼。(以上內(nèi)容是通過(guò)Google翻譯的官網(wǎng)內(nèi)容可能理解有些偏差屆時(shí)還望指正,事實(shí)上我在做實(shí)驗(yàn)的過(guò)程中蜀撑,發(fā)現(xiàn)使用NSThreadcancel方法是無(wú)法停止RunLoop的挤巡,cancel方法是更改線程的取消狀態(tài),指示它應(yīng)該退出酷麦。在當(dāng)前線程下執(zhí)行[NSThread exit]方法矿卑,退出了該線程,但demo中的LongLifeThreadViewController仍然未被釋放)

方式二:?jiǎn)?dòng)RunLoop時(shí)設(shè)定時(shí)限沃饶,RunLoop將一直運(yùn)行直到事件到達(dá)或分配的時(shí)間到期母廷。如果事件到達(dá)轻黑,則將該事件分派給處理程序進(jìn)行處理,然后退出此次RunLoop琴昆∶ケ桑可以通過(guò)重新啟動(dòng)RunLoop處理下一個(gè)事件。同樣如果分配的時(shí)間到期椎咧,也可以重新啟動(dòng)RunLoop來(lái)處理玖详。這種方式可以指定RunLoopMode,官網(wǎng)力薦勤讽。

自定義輸入源線程通信:

定義輸入源:

  1. 提供輸入源要處理的信息蟋座。
  2. 接收到事件時(shí)的執(zhí)行例程。
  3. 輸入源加到RunLoop時(shí)的執(zhí)行例程脚牍。
  4. 輸入源失效時(shí)的執(zhí)行例程向臀。

個(gè)人感覺可以根據(jù)個(gè)人需求決定是否實(shí)現(xiàn)第3、4兩條內(nèi)容诸狭。(注意定義輸入源只能通過(guò)CoreFoundation提供的對(duì)應(yīng)API實(shí)現(xiàn)券膀,其中的回調(diào)例程由C語(yǔ)言實(shí)現(xiàn))

RunLoop上安裝輸入源:如果實(shí)現(xiàn)了上述的第3條內(nèi)容時(shí),將自定義的輸入源添加到RunLoop時(shí)驯遇,就會(huì)回調(diào)輸入源對(duì)應(yīng)的schedule實(shí)現(xiàn)例程芹彬。

向輸入源發(fā)送信號(hào):輸入源在接收到信號(hào)后,會(huì)執(zhí)行對(duì)應(yīng)的perform例程叉庐,perform例程就是對(duì)應(yīng)事件處理程序舒帮。(注意如果線程處于休眠狀態(tài),要喚醒線程陡叠,否則該事件無(wú)法被處理玩郊。


結(jié)語(yǔ):
關(guān)于RunLoop的內(nèi)容還有很多,比如:RunLoopModes枉阵、RunLoopObserver译红、NSPortNSTimer等等兴溜,當(dāng)然還有RunLoop的源碼侦厚,這些內(nèi)容在此并未列出,如有感興趣的小伙伴可以先行花時(shí)間去探索拙徽、學(xué)習(xí)刨沦,到時(shí)可以一起交流、討論斋攀。

源碼地址:QiRunLoopDemo1


推薦文章:
iOS 常用調(diào)試方法:LLDB命令
iOS 常用調(diào)試方法:斷點(diǎn)
iOS 常用調(diào)試方法:靜態(tài)分析
iOS消息轉(zhuǎn)發(fā)
iOS 自定義拖拽式控件:QiDragView
iOS 自定義卡片式控件:QiCardView
iOS Wireshark抓包
iOS Charles抓包

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末已卷,一起剝皮案震驚了整個(gè)濱河市梧田,隨后出現(xiàn)的幾起案子淳蔼,更是在濱河造成了極大的恐慌侧蘸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹉梨,死亡現(xiàn)場(chǎng)離奇詭異讳癌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)存皂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門晌坤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人旦袋,你說(shuō)我怎么就攤上這事骤菠。” “怎么了疤孕?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵商乎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我祭阀,道長(zhǎng)鹉戚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任专控,我火速辦了婚禮抹凳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伦腐。我一直安慰自己赢底,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布蔗牡。 她就那樣靜靜地躺著颖系,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辩越。 梳的紋絲不亂的頭發(fā)上嘁扼,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音黔攒,去河邊找鬼趁啸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛督惰,可吹牛的內(nèi)容都是我干的不傅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼赏胚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼访娶!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起觉阅,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤崖疤,失蹤者是張志新(化名)和其女友劉穎秘车,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體劫哼,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叮趴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了权烧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眯亦。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖般码,靈堂內(nèi)的尸體忽然破棺而出妻率,到底是詐尸還是另有隱情,我是刑警寧澤板祝,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布舌涨,位于F島的核電站,受9級(jí)特大地震影響扔字,放射性物質(zhì)發(fā)生泄漏囊嘉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一革为、第九天 我趴在偏房一處隱蔽的房頂上張望扭粱。 院中可真熱鬧,春花似錦震檩、人聲如沸琢蛤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)博其。三九已至,卻和暖如春迂猴,著一層夾襖步出監(jiān)牢的瞬間慕淡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工沸毁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峰髓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓息尺,卻偏偏與公主長(zhǎng)得像携兵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搂誉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345