iOS 知識整理--Runloop

目錄

Runloop--概念

Runloop--獲取Runloop對象

Runloop--與線程的關係

Runloop--五大相關類

Runloop--應用

Runloop--面試題

RunLoop--注意點

 


Runloop--概念

基本作用:

  1. 保持程序的持續運行
  2. 處理App中的各種事件(比如觸摸事假、定時事件、selector事件)
  3. 節省CPU資源,提高程序性能:該做事時做事,改休息時休息。

iOS中有2套API來訪問和使用Runloop:

  1. Foundation NSRunloop
  2. Core Foundation CFRunLoopRef

Runloop--獲取Runloop對象

  • Foundation

[NSRunloop currentRunLoop];//獲取當前線程的Runloop對象

[NSRunloop mainRunLoop];//獲取主線程的Runloop對象

  • Core Foundation

CFRunloopGetCurrent();//獲取當前線程的Runloop對象

CFRunLoopGetMain();//獲取主線程的Runloop對象

  • 互相轉化方法

mainRunLoop.getCFRunLoop

Runloop--與線程的關係

每條線程都有唯一的一個與之對應的Runloop對象

主線程的Runloop已經自動創建好了,子線程的Runloop需要手動創建

Runloop在第一次獲取時創建,在線程結束時銷燬

Runloop--五大相關類

Core Foundation 中關於 Runloop的5個類

  • CFRunLoopRef//本身
  • CFRunLoopModeRef//運行模式
  • CFRunLoopSourceRef//事件源輸入源
  • CFRunloopTimerRef//定時器
  • CFRunLoopObserverRef//監聽

CFRunLoopModeRef(運行模式)

CFRunLoopModeRef代表RunLoop的運行模式

  • 一個Runloop包含若干個Mode,每個Mode又包含若干個Source/Timer/Observer
  • 每次Runloop啓動時,只能指定其中一個 Mode,這個Mode被稱爲CurrentMode
  • 如果需要切換Mode,只能退出Loop,再重新指定一個Mode進入
  • 這樣做主要是爲了分隔開不同組的Source/Timer/Observer,讓其互不影響

系統默認註冊了5個Mode:

  • kCFRunLoopDefaultMode:App默認Mode,通常主線程是在這個Mode下運行
  • UITrackingRunLoopMode:界面跟蹤Mode,用於ScrollView追蹤觸摸滑動,保證界面滑動時不受其他Mode影響
  • UIIntiallizationRunLoopMode:在剛啓動App時進入的第一個Mode,啓動完成後就不再使用
  • GSEventReceiveRunLoopMode:接受系統事件的內部Mode,通常用不到
  • kCFRunLoopCommonModes:這是一個佔位用的Mode,不是一種真正的Mode

CFRunLoopSourceRef(輸入源)

是事件源(輸入源)

  • Source0:非基於Port的(用戶主動觸發的事件,點擊按鈕,拖拽表格)
  • Source1:基於Port的(系統內部的消息事件)

CFRunLoopTimerRef(定時器)

CFRunLoopTimerRef是基於時間的觸發器

基本上說的就是NSTimer

CFRunLoopObserverRef(觀察者)

是觀察者,能夠監聽RunLoop的改變狀態

//創建監聽者
/*
1.怎麼分配存儲空間
2.要監聽的狀態 kCFRunLoopAllActivities所有的狀態
3.是否持續監聽
4.優先級,總是傳0
5.當狀態改變時候回調
*/

    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        /*
         kCFRunLoopEntry = (1UL << 0),即將進入runloop
         kCFRunLoopBeforeTimers = (1UL << 1),即將處理timer事件
         kCFRunLoopBeforeSources = (1UL << 2),即將處理source事件
         kCFRunLoopBeforeWaiting = (1UL << 5),即將進入睡眠
         kCFRunLoopAfterWaiting = (1UL << 6),被喚醒
         kCFRunLoopExit = (1UL << 7),runloop退出
         kCFRunLoopAllActivities = 0x0FFFFFFFU
         */
        switch (activity) {
            case kCFRunLoopEntry:
                NSLog(@"即將進入runloop");
                break;
            case kCFRunLoopBeforeTimers:
                NSLog(@"即將處理timer事件");
                break;
            case kCFRunLoopBeforeSources:
                NSLog(@"即將處理source事件");
                break;
            case kCFRunLoopBeforeWaiting:
                NSLog(@"即將進入睡眠");
                break;
            case kCFRunLoopAfterWaiting:
                NSLog(@"被喚醒");
                break;
            case kCFRunLoopExit:
                NSLog(@"runloop退出");
                break;
            default:
                break;
        }      
    });

/*
1.要監聽哪個runloop
2.觀察者
3.運行模式
     NSDefaultRunLoopMode = kCFRunLoopDefaultMode
     NSRunLoopCommonModes = kCFRunLoopCommonModes
*/

    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
}

 

Runloop--應用

NSTimer

ImageView顯示

PerformSelector

常駐線程

自動釋放池

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

[runLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];

[runLoop run];

Runloop--面試題

1.什麼是RunLoop?

從字面意思看是運行循環、跑圈

其實它內部就是do-while循環,在這個循環內部不斷地處理各種任務(比如Source、Timer、Observer)一個線程對應一個RunLoop,主線程的RunLoop默認已經開啓,子線程的RunLoop得手動啓動(調用runloop方法)

RunLoop只能選擇一個Mode啓動,如果當前Mode中沒有任何Source(Sources0、Sources1)、Timer,那麼就直接退出RunLoop

 

2.自動釋放池什麼時候釋放?

第一次創建:啓動runloop

最後一次銷燬:runloop退出的時候

其他時候創建和銷燬:當runloop即將睡眠的時候銷燬之前的釋放池,重新創建一個新的

 

3.在開發中如何使用RunLoop?什麼應用場景?

開啓一個常駐線程(讓一個子線程不進入消亡狀態,等待其他線程發來消息,處理其他事件)

可以控制定時器在特定模式下執行

可以讓某些事件(行爲、任務)在特定模式下執行

可以添加Observer 監聽RunLoop的狀態,比如監聽點擊事件的處理(在所有點擊事件之前做一些事情)

 

RunLoop--注意點

1.子線程runloop默認不創建

NSRunloop *loop= [NSRunloop currentRunLoop];//創建子線程runloop

[Loop run];//開啓runloop

2.在runloop中有多個運行模式,但是runloop只能選擇一種模式運行

3.mode裏面至少有一個timer或者source

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章