RunLoop的簡單介紹

什么是RunLoop

  • 從字面意思來看:跑圈竿裂、運(yùn)動(dòng)循環(huán)
  • 基本用法:保持程序持續(xù)運(yùn)行、處理App中的各種事件(觸摸事件、定時(shí)器事件奢赂、SEL等等)
  • 為什么需要它:節(jié)省CPU資源、 提高性能

如果沒有RunLoop


    int main (int argc, char *argv[]) {
        NSLog(@"execute main function");
        return 0;
    }
    
  • 如果沒有RunLoop颈走,第三行完成后程序就結(jié)束了

如果有了RunLoop

    
    int main(int argc, char *argv[]) {
        BOOL running = YES;
        do {
            // 執(zhí)行各種任務(wù)膳灶,處理各種事件
            // ...
        } while (running);
        return 0;
    }

  • 由于main函數(shù)里面啟動(dòng)了RunLoop,所以程序保持持續(xù)運(yùn)行狀態(tài)

main函數(shù)里的RunLoop


    int main(int argc, char *argv[]) {
        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }
  • 在UIApplicationMain函數(shù)內(nèi)部就啟動(dòng)了一個(gè)RunLoop
  • 所以UIApplicationMain函數(shù)一直沒有返回立由,保持了程序的持續(xù)運(yùn)行
  • 這個(gè)默認(rèn)啟動(dòng)的RunLoop是根主線程相關(guān)聯(lián)的

RunLoop對象

  • iOS中有兩套API來訪問和使用RunLoop
  • Foundation中的NSRunloop
  • Core Foundation中的CFRunLoopRef
  • NSRunloop和CFRunLoopRef都代表著RunLoop對象
  • NSRunloop是基于CFRunLoopRef封裝的轧钓, 所以要了解RunLoop的內(nèi)部結(jié)構(gòu),還是要研究CFRunLoopRef(Core Foundation)層面的API

RunLoop與線程

  • 每條線程都有位移的一個(gè)與之對應(yīng)的RunLoop對象
  • 主線程的RunLoop一經(jīng)自動(dòng)創(chuàng)建好了锐膜,子線程的RunLoop需要主動(dòng)創(chuàng)建
  • RunLoop在第一次獲取時(shí)創(chuàng)建毕箍,在線程結(jié)束時(shí)銷毀

獲得RunLoop對象

  • Foundation

      // 獲得當(dāng)前線程的RunLoop對象 
    - [NSRunLoop currentRunLoop];
      // 獲得主線程的RunLoop對象
    - [NSRunLoop mainRunLoop];
    
  • Core Foundation

    // 獲得當(dāng)前線程的RunLoop對象
    CFRunLoopGetCurrent();
    // 獲得主線程的RunLoop對象
    CFRunLoopGetMain();

RunLoop的相關(guān)類

  • Core Foundation中關(guān)于RunLoop的5個(gè)類

    • CFRunLoopRef
    • CFRunLoopModeRef
    • CFRunLoopSourceRef
    • CFRunLoopTimerRef
    • CFRunLoopOberverRef
  • CFRunLoopModeRef

    • CFRunLoopModeRef代表RunLoop的運(yùn)行模式

    • 一個(gè)RunLoop包含若干個(gè)Mode,每個(gè)Mode有包含若干個(gè)Source/Timer/Observe

    • 每次RunLoop啟動(dòng)時(shí)道盏,只能指定其中一個(gè)Mode霉晕,這個(gè)Mode被稱作CurrentMode

    • 如果需要切換Mode,只能退出RunLoop捞奕,在重新指定一個(gè)RunLoop進(jìn)入

    • 這樣做主要是為了分隔開不同組的Source/Timer/Observe牺堰,讓其互不影響

    • 系統(tǒng)默認(rèn)注冊了5個(gè)Mode

      • kCFRunLoopDefaultMode:App的默認(rèn)Mode,通常主線程再是這個(gè)Mode下運(yùn)行的
      • UITrackingRunLoopMode:界面跟蹤Mode颅围, 用于ScrollView追蹤觸摸滑動(dòng)伟葫,保證界面滑動(dòng)時(shí)不受其他Mode影響
      • UIInitializionRunLoopMode:在剛啟動(dòng)App是進(jìn)入的第一個(gè)Mode,啟動(dòng)時(shí)完成后就不再使用
      • GSEcentRunLoopMode:接受系統(tǒng)時(shí)間的內(nèi)部Mode院促,通常不會用到
      • kCFRunLoopCommonMode:這是一個(gè)占位用的Mode筏养,不是真正的Mode
  • CFRunLoopSourceRef

    • CGRunLoopRef是事件源(輸入源)

      • 以前的分類方法

      • Port-Based Source

      • Custom Input Source

      • Cocoa Perform Selector Source

      • 現(xiàn)在的分類方法

      • Source0:不是基于Port的

      • Source1:基于Port的

  • CFRunLoopTimerRef

    • CFRunLoopTimerRef是基于事件的觸發(fā)器
    • 基本上說的就是NSTimer
  • CFRunLoopObserverRef

    • CFRunLoopObserverRef是觀察者,能夠監(jiān)聽RunLoop的狀態(tài)改變
    • 可以監(jiān)聽的時(shí)間點(diǎn)有以下幾個(gè)
    
          typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity)    {
            // 即將進(jìn)入Loop
           kCFRunLoopEntry                 =(1UL << 0),
            // 即將處理Timer
           kCFRunLoopBeforeTimers          =(1UL << 1),
            // 即將處理Source
           kCFRunLoopBeforeSource          =(1UL << 2),
            // 即將進(jìn)入休眠
           kCFRunLoopBeforeWaiting         =(1UL << 5),
            // 剛從休眠中喚醒
           kCFRunLoopAfterWaiting          =(1UL << 6),
            // 即將退出Loop
           kCFRunLoopExit                  =(1UL << 7),   
          }
      ```
    
    

RunLoop處理邏輯 - 官方版

RunLoop的事件隊(duì)列

  • 每次運(yùn)行RunLoop常拓,你的線程RunLoop會自動(dòng)處理之前未處理的消息渐溶,并通知相關(guān)的觀察者。具體順序如下

    • 1.通知觀察者RunLoop已經(jīng)啟動(dòng)

    • 2.通知觀察者任何將要開始的定時(shí)器

    • 3.通知觀察者任何即將啟動(dòng)的非基于端口的源

    • 4.啟動(dòng)任何準(zhǔn)備好的非基于端口的源

    • 5.如果基于端口的源準(zhǔn)備好并處于等待狀態(tài)弄抬,立即啟動(dòng)茎辐,并進(jìn)入步驟9

    • 6.通知觀察者線程進(jìn)入休眠

    • 7.將線程至于休眠狀態(tài)直到任一下面的事件發(fā)生:

      • 某一時(shí)間到達(dá)基于端口的源
      • 定時(shí)器啟動(dòng)
      • RunLoop設(shè)置的事件已經(jīng)超時(shí)
      • RunLoop被顯式喚醒
    • 8.通知觀察者線程將被喚醒

    • 9.處理未處理的事件

      • 如果用戶定義的定時(shí)器啟動(dòng), 處理定時(shí)器事件并重啟RunLoop掂恕,進(jìn)入步驟2
      • 如果輸入源啟動(dòng)拖陆,傳遞相應(yīng)的消息
        如果RunLoop被顯式喚醒而且事件還沒超時(shí),重啟RunLoop懊亡,進(jìn)入步驟2
    • 10.通知觀察者RunLoop結(jié)束

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末依啰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子店枣,更是在濱河造成了極大的恐慌速警,老刑警劉巖叹誉,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異闷旧,居然都是意外死亡桂对,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門鸠匀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人逾柿,你說我怎么就攤上這事缀棍。” “怎么了机错?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵爬范,是天一觀的道長。 經(jīng)常有香客問我弱匪,道長青瀑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任萧诫,我火速辦了婚禮斥难,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帘饶。我一直安慰自己哑诊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布及刻。 她就那樣靜靜地躺著镀裤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缴饭。 梳的紋絲不亂的頭發(fā)上暑劝,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音颗搂,去河邊找鬼担猛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丢氢,可吹牛的內(nèi)容都是我干的毁习。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼卖丸,長吁一口氣:“原來是場噩夢啊……” “哼纺且!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起稍浆,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤载碌,失蹤者是張志新(化名)和其女友劉穎猜嘱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嫁艇,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朗伶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了步咪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片论皆。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猾漫,靈堂內(nèi)的尸體忽然破棺而出点晴,到底是詐尸還是另有隱情,我是刑警寧澤悯周,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布粒督,位于F島的核電站,受9級特大地震影響禽翼,放射性物質(zhì)發(fā)生泄漏屠橄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一闰挡、第九天 我趴在偏房一處隱蔽的房頂上張望锐墙。 院中可真熱鬧,春花似錦长酗、人聲如沸贮匕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刻盐。三九已至,卻和暖如春劳翰,著一層夾襖步出監(jiān)牢的瞬間敦锌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工佳簸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乙墙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓生均,卻偏偏與公主長得像听想,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子马胧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

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