iOS 中Runloop

Runloop 字面理解為運(yùn)行循環(huán)

作用:
1,保持程序的持續(xù)運(yùn)行。
2,處理程序中的各種事件,比如觸摸事件,定時(shí)器事件。Selector方法。
3,節(jié)省CPU資源,提高程序性能。該做事時(shí)做事,該休息時(shí)休息(Runloop的狀態(tài))

iOS中有兩套API訪問Runloop
1,F(xiàn)oundation框架
NSRunloop
2,Core Foundation框架
CFRunloopRef

NSRunloop是基于CFRunloopRef的封裝

一,runloop與線程的關(guān)系
1,每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的runloop
2,主線程的runloop已經(jīng)自動(dòng)創(chuàng)建好了,子線程的runloop需要主動(dòng)創(chuàng)建。
3,runloop在第一次獲取時(shí)創(chuàng)建,在線程結(jié)束時(shí)銷毀。

二,CFRunloopModeRef
CFRunloopModeRef代表Runloop的運(yùn)行模式
1,一個(gè)Runloop包含多個(gè)運(yùn)行模式Mode,每個(gè)Mode又包含若干個(gè)Source/Timer/Observer。
2,每次Runloop啟動(dòng)時(shí)只能啟動(dòng)一個(gè)mode,稱之為currentmode,可通過此方法獲取。
3,如果要切換mode,只能先退出loop,再重新指定一個(gè)Mode進(jìn)入。

系統(tǒng)默認(rèn)為我們注冊(cè)了5種運(yùn)行模式,這里只介紹公開暴露出來的兩種

NSDefaultRunLoopMode 默認(rèn)Mode,通常主線程運(yùn)行模式。
NSEventTrackingRunLoopMode 界面跟蹤Mode,ScrollView追蹤滑動(dòng)觸摸,保證界面滑動(dòng)時(shí)不受其他Mode影響。
NSRunLoopCommonModes 標(biāo)簽,被標(biāo)記的對(duì)象可以運(yùn)行在被標(biāo)簽標(biāo)記的模式下,隨著模式的切換而切換,比如NSTimer。

iOS 中公開暴露出來的只有 NSDefaultRunLoopMode 和 NSRunLoopCommonModes。 NSRunLoopCommonModes 實(shí)際上是一個(gè) Mode 的集合,默認(rèn)包括 NSDefaultRunLoopMode 和 NSEventTrackingRunLoopMode(注意:并不是說Runloop會(huì)運(yùn)行在kCFRunLoopCommonModes這種模式下,而是相當(dāng)于分別注冊(cè)了 NSDefaultRunLoopMode和 UITrackingRunLoopMode。當(dāng)然你也可以通過調(diào)用CFRunLoopAddCommonMode()方法將自定義Mode放到 kCFRunLoopCommonModes組合)。

三,CFRunLoopSourceRef
以前分類:
1,Port
2,Custom,Input Source
3,performselector
現(xiàn)在:
1,Source0:
非基于port的,用戶主動(dòng)觸發(fā)的,如觸摸等
2,Source1:
基于Port的,基于內(nèi)核和其他線程相互發(fā)送消息。

四,CFRunLoopObserverRef
CFRunLoopObserver是觀察者,可以觀察RunLoop的各種狀態(tài),并拋出回調(diào)。

struct __CFRunLoopObserver {
    CFRuntimeBase _base;
    pthread_mutex_t _lock;
    CFRunLoopRef _runLoop;
    CFIndex _rlCount;
    CFOptionFlags _activities;      /* immutable */
    CFIndex _order;         /* immutable */
    CFRunLoopObserverCallBack _callout; /* immutable */
    CFRunLoopObserverContext _context;  /* immutable, except invalidation */
};

CFRunLoopObserver可以觀察的狀態(tài)有如下6種:

/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0), //即將進(jìn)入run loop
    kCFRunLoopBeforeTimers = (1UL << 1), //即將處理timer
    kCFRunLoopBeforeSources = (1UL << 2),//即將處理source
    kCFRunLoopBeforeWaiting = (1UL << 5),//即將進(jìn)入休眠
    kCFRunLoopAfterWaiting = (1UL << 6),//被喚醒但是還沒開始處理事件
    kCFRunLoopExit = (1UL << 7),//run loop已經(jīng)退出
    kCFRunLoopAllActivities = 0x0FFFFFFFU
};
什么是Runloop?

字面意思是一個(gè)運(yùn)行循環(huán),其實(shí)內(nèi)部是一個(gè)do while 循環(huán),在處理各種事件,timer,source,Observer。
一個(gè)線程對(duì)應(yīng)一個(gè)Runloop。主線程自動(dòng)啟動(dòng),子線程需要手動(dòng)啟動(dòng),調(diào)用Run方法。
Runloop只能選擇一個(gè)模式啟動(dòng),更改模式需要先退出再進(jìn)入新模式。如果Model沒有任何timer。source,那么直接退出runloop。

自動(dòng)釋放池什么時(shí)候釋放?

根據(jù)Observer觀察的Runloop狀態(tài)釋放,runloop退出。

五,Runloop應(yīng)用
1,NSTimer
定時(shí)器設(shè)置為CommonMode更精準(zhǔn)
2,ImageVIew顯示
將圖片的顯示設(shè)置在UITracking模式,可以保證在列表滑動(dòng)的時(shí)候依然能夠加載視圖。
3,PerformSeletor
4,常駐線程
創(chuàng)建一個(gè)Runloop在子線程一直運(yùn)行,保證線程在后臺(tái)常駐(AFNetworking源碼)。

子線程的Runloop需要手動(dòng)調(diào)用,然后添加一個(gè)Source或者Timer事件,再調(diào)用Run方法。

5,自動(dòng)釋放池
Runloop內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)自動(dòng)釋放池,開始的時(shí)候創(chuàng)建,等到合適的時(shí)機(jī)再釋放,通過觀察Runloop狀態(tài)來進(jìn)行。

6,通過對(duì)Runloop添加Observer來做一些事情
(1),比如監(jiān)聽點(diǎn)擊事件,當(dāng)runloop處理點(diǎn)擊事件時(shí)候可以統(tǒng)一做一些事情。
(2),也可以通過對(duì)Runloop狀態(tài)的觀察來檢測(cè)系統(tǒng)卡頓,當(dāng)長時(shí)間處于一個(gè)模式不變就是出現(xiàn)了卡頓。

//創(chuàng)建子線程監(jiān)控
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    //子線程開啟一個(gè)持續(xù)的 loop 用來進(jìn)行監(jiān)控
    while (YES) {
        long semaphoreWait = dispatch_semaphore_wait(dispatchSemaphore, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));
        if (semaphoreWait != 0) {
            if (!runLoopObserver) {
                timeoutCount = 0;
                dispatchSemaphore = 0;
                runLoopActivity = 0;
                return;
            }
            //BeforeSources 和 AfterWaiting 這兩個(gè)狀態(tài)能夠檢測(cè)到是否卡頓
            if (runLoopActivity == kCFRunLoopBeforeSources || runLoopActivity == kCFRunLoopAfterWaiting) {
                //將堆棧信息上報(bào)服務(wù)器的代碼放到這里
            } //end activity
        }// end semaphore wait
        timeoutCount = 0;
    }// end while
});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ======================= 前言 RunLoop 是 iOS 和 OSX 開發(fā)中非?;A(chǔ)的一個(gè)...
    i憬銘閱讀 1,000評(píng)論 0 4
  • 概述 RunLoop作為iOS中一個(gè)基礎(chǔ)組件和線程有著千絲萬縷的關(guān)系,同時(shí)也是很多常見技術(shù)的幕后功臣。盡管在平時(shí)多...
    sumrain_cloud閱讀 1,010評(píng)論 0 5
  • 1.不開啟RunLoop的線程在遇到一些耗時(shí)操作時(shí),為了避免主線程阻塞導(dǎo)致界面卡頓,影響用戶體驗(yàn),往往我們會(huì)把這些...
    shinedada閱讀 417評(píng)論 0 2
  • 本文我主要是學(xué)習(xí)如下文章做的記錄,同時(shí)還有其他優(yōu)秀的文章沒有粘貼出來,在這里均表示感謝。iOS RunLoop入門...
    wg剛閱讀 464評(píng)論 0 1
  • 轉(zhuǎn)自bireme,原地址:https://blog.ibireme.com/2015/05/18/runloop/...
    乜_啊_閱讀 1,689評(píng)論 0 5

友情鏈接更多精彩內(nèi)容