RunLoop 在應用中的基本使用

RunLoop應用場景

  1. 開啟一個常駐線程(讓一個子線程不進入消亡狀態(tài),等待其他線程發(fā)來消息,處理其他事件)
    • 在子線程中開啟一個定時器(或添加port)
    • 在子線程中進行一些長期監(jiān)控
  2. 可以控制定時器在哪種模式下運行
  3. 可以讓某些事件(行為、任務)在特定模式下執(zhí)行
  4. 可以添加Observer監(jiān)聽RunLoop的狀態(tài),比如監(jiān)聽點擊事件的處理(在所有點擊事件之前做一些事情)

常駐線程

讓一個子線程不進入消亡狀態(tài),等待其他線程發(fā)來消息,處理其他事件

  1. 聲明一個NSThread屬性:@property (nonatomic, strong) NSThread *thread;
  2. 開啟線程
- (void)viewDidLoad {
    [super viewDidLoad];
    self.thread = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
    [self.thread start];
}

- (void)run {
    // RunLoop如果當前mode中沒有任何Sources(Source0、Source1)、Timer,那么就會直接退出RunLoop
    @autoreleasepool {
        // 在此線程開啟RunLoop ---> 讓線程不死
        [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; // 添加port相當于添加Source
        [[NSRunLoop currentRunLoop] run]; 
    }
}

注意:常駐線程啟動RunLoop最好放到autoreleasepool里面
作用:清掉創(chuàng)建的臨時變量(主線程的RunLoop會自動在RunLoop睡眠前釋放舊的釋放池然后自動創(chuàng)建新的釋放池,子線程的RunLoop最好添加個大釋放池包裹住)

  1. 往常駐線程中發(fā)送消息
[self performSelector:@selector(work) onThread:self.thread withObject:nil waitUntilDone:NO];

常駐線程的好處

  • 讓一個子線程不進入消亡狀態(tài),等待其他線程發(fā)來消息,處理其他事件(AFNetworking框架里面就使用了常駐線程)

定時器與RunLoop

控制定時器在哪種模式下運行

NSTimer:

  • scheduledTimerWithTimeInterval ---- 自動添加到當前RunLoop中,而且是NSDefaultRunLoopMode,可手動修改模式
  • timerWithTimeInterval ---- 需要手動添加到runLoop
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timer) userInfo:nil repeats:YES];
// 將定時器放入RunLoop中
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

模式:

  • NSDefaultRunLoopMode:一旦RunLoop進入其他模式(例如滾動的mode),這個定時器就不會工作
  • NSRunLoopCommonModes:將定時器加入到標記為common modes的模式下,只要RunLoop知道有這個模式的存在,不管RunLoop在哪個模式都會執(zhí)行這個標記的模式(即使在滾動的UITrackingRunLoopMode下也會執(zhí)行)

Observer與RunLoop

添加Observer監(jiān)聽RunLoop的狀態(tài),比如監(jiān)聽點擊事件的處理(在所有點擊事件之前做一些事情)

// 創(chuàng)建觀察者
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
    // 狀態(tài)改變時回調(diào)的block
    NSLog(@"RunLoop狀態(tài) %lu",activity);
});
    
// 添加觀察者:監(jiān)聽RunLoop的狀態(tài)
// 參數(shù)1:線程的RunLoop對象
// 參數(shù)2:觀察者
// 參數(shù)3:需要監(jiān)聽RunLoop對象所在的模式
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
    
// ARC模式下C語言層面的對象需要手動釋放內(nèi)存
// 釋放Observer
CFRelease(observer);

注意:創(chuàng)建了Observer記得要release

RunLoop的狀態(tài)

  • kCFRunLoopEntry = (1UL << 0), //即將進入loop 1
  • kCFRunLoopBeforeTimers = (1UL << 1), //即將處理Timer 2
  • kCFRunLoopBeforeSources = (1UL << 2), //即將處理Sources 4
  • kCFRunLoopBeforeWaiting = (1UL << 5), //即將進入休眠 32
  • kCFRunLoopAfterWaiting = (1UL << 6), //剛從休眠中喚醒 64
  • kCFRunLoopExit = (1UL << 7), //即將退出loop 128
  • kCFRunLoopAllActivities = 0x0FFFFFFFU //所有狀態(tài)
UL是無符號長整數(shù)的意思
    1UL<<0:0b00000001
    1UL<<1:0b00000010
    1UL<<2:0b00000100
    1UL<<3:0b00001000
0x0FFFFFFF是整形int變量里能保存的最大數(shù)

讓某些事件(行為、任務)在特定模式下執(zhí)行

設置圖片不在滾動視圖滾動期間顯示

[self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"01"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

  • 一、什么是runloop 字面意思是“消息循環(huán)、運行循環(huán)”。它不是線程,但它和線程息息相關。一般來講,一個線程一次...
    WeiHing閱讀 8,306評論 11 111
  • ======================= 前言 RunLoop 是 iOS 和 OSX 開發(fā)中非常基礎的一個...
    i憬銘閱讀 989評論 0 4
  • runtime 和 runloop 作為一個程序員進階是必須的,也是非常重要的, 在面試過程中是經(jīng)常會被問到的, ...
    made_China閱讀 1,273評論 0 7
  • runtime 和 runloop 作為一個程序員進階是必須的,也是非常重要的, 在面試過程中是經(jīng)常會被問到的, ...
    SOI閱讀 22,025評論 3 63
  • RunLoop 文章目錄 RunLoop簡介 1.1 什么是RunLoop? 1.2 RunLoop和線程 1.3...
    May_d8f1閱讀 345評論 0 1

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