iOS runloop

寫這篇文章開始之前棉胀,我都不知道runloop是什么東西,如果從字面的意思翻譯應(yīng)該是一直循環(huán)的跑法瑟,懷疑可能和死鎖有關(guān)系,可是死鎖具體是怎么回事唁奢,我只是記得有這個說法霎挟,也發(fā)現(xiàn)了一個自己不懂的知識。

初識runloop

我在網(wǎng)上看了一下@sunnnyxx 關(guān)于runloop的視頻.了解了一下runloop相關(guān)知識,也去網(wǎng)絡(luò)上看各種關(guān)于runloop的講述麻掸。

我們一般程序就是執(zhí)行一個線程酥夭,是一條直線.有起點(diǎn)終點(diǎn).而runloop就是一直在線程上面畫圓圈,一直在跑圈脊奋,除非切斷否則一直在運(yùn)行熬北。網(wǎng)上說的比喻很好,直線就像曇花一現(xiàn)一樣诚隙,圓就像OS,一直運(yùn)行直到你關(guān)機(jī)為止讶隐。

在我們學(xué)習(xí)iOS生命周期里面都會存在銷毀的過程,但是屏幕好像一直能接收各種指令最楷,感覺很像runloop的功效,好像這些是和頂層UIKit無關(guān),IOS架構(gòu)最底層是Core OS,我分析應(yīng)該是蘋果封裝好了整份,只是我們看不到源碼而已待错。


為什么要使用runloop

@sunnnyxx 在視頻介紹了四個作用:

  • 使程序一直運(yùn)行接受用戶輸入
  • 決定程序在何時應(yīng)該處理哪些Event
  • 調(diào)用解耦(對于編程經(jīng)驗為0的完全沒搞懂這個意思,解釋為Message Queue)
  • 節(jié)省CPU時間

這段視頻我覺得不太適合小白去看,因為好多概念還沒有融會貫通烈评,也沒有理解透徹火俄。但是既然看了,就得總結(jié)一下讲冠,至少產(chǎn)生一個樹突先瓜客,留下一個問號,未來把問號變成嘆號竿开。

回到開始的疑問,為什么要使用RunLoop,一般情況下我們是沒必要去啟動線程的RunLoop谱仪,除非需要在一個單獨(dú)的線程長久的檢測某個事件,就像視頻里面提到的類似微信的語音功能否彩,見一個RunLoop專門負(fù)責(zé)監(jiān)聽說話的線程疯攒。看需求而定了列荔。


CFRunLoopSource

Source是RunLoop的數(shù)據(jù)源抽象類,類似IOS中的protocol

RunLoop定義兩個Version的Source

  • Source0:處理App內(nèi)部事件,App自己負(fù)責(zé)管理(觸發(fā)),如UIEvent,CFSocket
  • Source1:由RunLoop和內(nèi)核管理,Mach port驅(qū)動 如CFMach敬尺、CFMessage

CFRunLoopObserver

向內(nèi)部報告RunLoop當(dāng)前狀態(tài)的更改 CAAnimation

RunLoopObserver 與 Autorelease Pool

UIKit通過RunLoopObserver在RunLoop兩次Sleep間對AutoreleasePool進(jìn)行pop和push,將這次Loop中產(chǎn)生的Autorelease對象釋放。(好像swift中沒有關(guān)于釋放的問題)

CFRunLoopMode

RunLoop在同一時段只能且必須在一種特定Mode下Run
更換Mode時, 需要暫停當(dāng)前的Loop,然后重啟新的Loop

  • NSDefalutRunLoopMode? ? ? 默認(rèn)狀態(tài).空閑狀態(tài)
  • UITrackingRunLoopMode? ? ?滑動ScrollView
  • UIInitializationRunLoopMode? ? 私有,App啟動時
  • NSRunLoopCommonModes? ? ?默認(rèn)包括上面第一和第二

UITrackingRunLoopMode 與 NSTimer

默認(rèn)情況下NSTimer被加入NSDefalutRunLoopMode
如果想NSTimer受到組件或者動畫影響 添加到NSRunLoopCommonModes(OC代碼如下:)

  [[NSRunLoop currentRunLoop]addTimer:timer...forMode:NSRunLoopCommonModes];

swift版代碼:

 NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)

RunLoopMode切換

NSDefaultRunLoopMode->UITrackingRunLoopMode->NSDefalutRunLoopMode

RunLoop的掛起與喚醒

  • 制定用于喚醒的mach_port端口
  • 調(diào)用mach_msg監(jiān)聽喚醒端口,被喚醒前,系統(tǒng)內(nèi)核將這個線程掛起,停留在mach_msg_trap
  • 由另外一個線程(或另一個進(jìn)程中的某個線程)向內(nèi)核發(fā)送這個端口的msg后,trap狀態(tài)被喚醒,RunLoop繼續(xù)開始干活

AFNetWorking 中創(chuàng)建RunLoop

創(chuàng)建一個常駐服務(wù)線程的很好方法

 [[NSThread currentThread] setName:@"AFNetworking"];
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefalutRunLoopMode]//一直活著
[runLoop run];

swift版代碼

var loop = NSRunLoop.currentRunLoop()
loop.addPort(NSMachPort(), forMode: NSDefaultRunLoopMode)
loop.run()

一個TableView延遲加載圖片的新思路

[self.avatarImageView performSelector:@selector(serImage:)  
                        withObjetc:downloadedImage
                        afterDelay:0
                        inModes:@[NSDefaultRunLoopMode]]
 + (NSThread *)networkRequestThread {
      static NSThread *_networkRequestThread = nil;
      static dispatch_once_t oncePredicate;
      dispatch_once(&oncePredicate, ^{
      _networkRequestThread =
      [[NSThread alloc] initWithTarget:self
           selector:@selector(networkRequestThreadEntryPoint:)
           object:nil];
      [_networkRequestThread start];
 });

 return _networkRequestThread;

}
這個代碼無法轉(zhuǎn)換成swift贴浙,可能是我沒想到辦法砂吞,大家誰找到了請評論,謝謝了崎溃。


讓Crash的App回光返照 只針對Signal Crash

CFRunLoopRef runloop = CFRunLoopGetCurrent();
NSArray *allModes = CFBridgingRelease(CFRunLoopCopyAllModes(runLoop));
while(1){
    for (NSString *mode in allModes){
        CFRunLoopInMode((CFStringRef)mode,0.001,false);
    }
}

RunLoop事件隊列
每次運(yùn)行run loop蜻直,你線程的run loop對會自動處理之前未處理的消息,并通知相關(guān)的觀察者袁串。具體的順序如下:

  1. 通知觀察者run loop已經(jīng)啟動
  2. 通知觀察者任何即將要開始的定時器
  3. 通知觀察者任何即將啟動的非基于端口的源
  4. 啟動任何準(zhǔn)備好的非基于端口的源
  5. 如果基于端口的源準(zhǔn)備好并處于等待狀態(tài)概而,立即啟動;并進(jìn)入步驟9般婆。
  6. 通知觀察者線程進(jìn)入休眠
  7. 將線程置于休眠直到任一下面的事件發(fā)生:
  • 某一事件到達(dá)基于端口的源
  • 定時器啟動
  • Run loop設(shè)置的時間已經(jīng)超時
  • run loop被顯式喚醒
  1. 通知觀察者線程將被喚醒到腥。
  2. 處理未處理的事件
  • 如果用戶定義的定時器啟動,處理定時器事件并重啟run loop蔚袍。進(jìn)入步驟2
  • 如果輸入源啟動,傳遞相應(yīng)的消息
  • 如果run loop被顯式喚醒而且時間還沒超時配名,重啟run loop啤咽。進(jìn)入步驟2
  1. 通知觀察者run loop結(jié)束。

異步測試

- (BOOL)runUntilBlock:(BOOL(^)())block timeout:(NSTimeInterval)timeout{   
      __block Boolean fulfilled = NO;
      void (^beforeWaiting) (CFRunLoopObserverRef observer, CFRunLoopActivity activity) =
 ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
      fulfilled = block();
      if (fulfilled) {
           CFRunLoopStop(CFRunLoopGetCurrent());
      }
 };

 CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, 0, beforeWaiting);
 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

 // Run!
 CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, false);

 CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
 CFRelease(observer);

 return fulfilled;

}


總結(jié)一下

基本上對于RunLoop渠脉,我只能說我只有簡單的模糊印象宇整,但是不理解,也不太清楚在現(xiàn)實(shí)如何使用芋膘,因為實(shí)踐才能知道如何做鳞青,真的在腦里形成了樹突霸饲,希望在未來搞定,研究透徹臂拓『衤觯看這些代碼時候我發(fā)現(xiàn)我的基礎(chǔ)知識還需要鞏固。感謝不相識的孫源胶惰。
聲明一點(diǎn):不要只去收藏傻工,去看看代碼有沒有問題,知識有沒有解釋錯誤的孵滞,交流學(xué)的更快中捆。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坊饶,隨后出現(xiàn)的幾起案子泄伪,更是在濱河造成了極大的恐慌,老刑警劉巖匿级,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臂容,死亡現(xiàn)場離奇詭異,居然都是意外死亡根蟹,警方通過查閱死者的電腦和手機(jī)脓杉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來简逮,“玉大人球散,你說我怎么就攤上這事∩⑹” “怎么了蕉堰?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長悲龟。 經(jīng)常有香客問我屋讶,道長,這世上最難降的妖魔是什么须教? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任皿渗,我火速辦了婚禮,結(jié)果婚禮上轻腺,老公的妹妹穿的比我還像新娘乐疆。我一直安慰自己,他們只是感情好贬养,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布挤土。 她就那樣靜靜地躺著,像睡著了一般误算。 火紅的嫁衣襯著肌膚如雪仰美。 梳的紋絲不亂的頭發(fā)上迷殿,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機(jī)與錄音咖杂,去河邊找鬼庆寺。 笑死,一個胖子當(dāng)著我的面吹牛翰苫,可吹牛的內(nèi)容都是我干的止邮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼奏窑,長吁一口氣:“原來是場噩夢啊……” “哼导披!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起埃唯,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤撩匕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后墨叛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體止毕,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年漠趁,在試婚紗的時候發(fā)現(xiàn)自己被綠了扁凛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡闯传,死狀恐怖谨朝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甥绿,我是刑警寧澤字币,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站共缕,受9級特大地震影響洗出,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜图谷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一翩活、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜓萄,春花似錦隅茎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俏竞。三九已至绸硕,卻和暖如春堂竟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背玻佩。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工出嘹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人咬崔。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓税稼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親垮斯。 傳聞我的和親對象是個殘疾皇子郎仆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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