iOS RunLoop

一、簡(jiǎn)介

  • 什么是RunLoop

    • 運(yùn)行循環(huán)
    • 基本作用:
      • 保持程序的持續(xù)運(yùn)行,如果沒(méi)有RunLoop,程序執(zhí)行完main函數(shù)就結(jié)束了。
      • 處理App中的各種事件(比如觸摸事件、定時(shí)器事件、Selector事件)
      • 節(jié)省CPU資源,提高程序性能:該做事時(shí)做事,該休息時(shí)休息
      • ......
  • main函數(shù)中的RunLoop

    • 在UIApplicationMain函數(shù)內(nèi)部就啟動(dòng)了一個(gè)RunLoop,所以UIApplicationMain函數(shù)一直沒(méi)有返回,保持了程序的持續(xù)運(yùn)行
    • 這個(gè)默認(rèn)啟動(dòng)的RunLoop是跟主線程相關(guān)聯(lián)的
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 
    }
}

二、RunLoop與線程

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

獲得RunLoop對(duì)象

  • iOS中有2套API來(lái)訪問(wèn)和使用RunLoop

    • 1.Foundation : NSRunLoop
    • 2.CoreFoundation : CFRunLoopRef
    • NSRunLoop和CFRunLoopRef都代表著RunLoop對(duì)象
  • Foundation

[NSRunLoop currentRunLoop];// 獲得當(dāng)前線程的RunLoop對(duì)象
[NSRunLoop mainRunLoop];// 獲得主線程的RunLoop對(duì)象
  • CoreFoundation
CFRunLoopGetCurrent();// 獲得當(dāng)前線程的RunLoop對(duì)象
CFRunLoopGetMain();// 獲得主線程的RunLoop對(duì)象

三、RunLoop相關(guān)資料

四、RunLoop相關(guān)類

  • CoreFoundation中關(guān)于RunLoop的5個(gè)類
    • CFRunLoopRef
    • CFRunLoopModeRef
    • CFRunLoopSourceRef
    • CFRunLoopTimerRef
    • CFRunLoopObserverRef
runLoop相關(guān)類.png

CFRunLoopModeRef

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

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

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

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

  • 這樣做主要是為了分隔開(kāi)不同組的Source/Timer/Observer,讓其互不影響

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

    • NSDefaultRunLoopMode: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,通常用不到
  • NSRunLoopCommonModes: 這是一個(gè)占位用的Mode,不是一種真正的Mode

CFRunLoopSourceRef

  • CFRunLoopTimerRef是基于時(shí)間的觸發(fā)器
  • CFRunLoopTimerRef基本上說(shuō)的就是NSTimer,它受RunLoop的Mode影響
  • 注意: GCD的定時(shí)器不受RunLoop的Mode影響

CFRunLoopSourceRef

  • CFRunLoopSourceRef是事件源(輸入源)

  • 按照官方文檔,Source的分類

    • Port-BasedSources
    • Custom InputSources
    • Cocoa PerformSelector Sources
  • 按照函數(shù)調(diào)用棧,Source的分類

    • Source0:非基于Port的, 用于用戶主動(dòng)觸發(fā)事件
    • Source1:基于Port的,通過(guò)內(nèi)核和其他線程相互發(fā)送消息

CFRunLoopObserverRef

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

  • 可以監(jiān)聽(tīng)的時(shí)間點(diǎn)有以下幾個(gè)

監(jiān)聽(tīng)時(shí)間點(diǎn).png
  • 添加Observer
//創(chuàng)建observer
CFRunLoopObserverRefobserver = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(),kCFRunLoopAllActivities,YES,0,^(CFRunLoopObserverRefobserver, CFRunLoopActivityactivity) {
    NSLog(@"----監(jiān)聽(tīng)到RunLoop狀態(tài)發(fā)生改變---%zd",activity);
});

//添加觀察者:監(jiān)聽(tīng)RunLoop的狀態(tài)
CFRunLoopAddObserver(CFRunLoopGetCurrent(),observer, kCFRunLoopDefaultMode);

//釋放Observer
CFRelease(observer);
最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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