iOS RunLoop

RunLoop概念

  • RunLoop是經過內部維護的事件循環(Event Loop)來對事件/消息進行管理的一個對象
  • 沒有消息處理時,休眠以免資源佔用;有消息須要處理時,馬上被喚醒
  1. 爲何main函數不會退出
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
複製代碼

UIApplicationMain內部默認開啓了主線程的RunLoop,並執行了一段無限循環的代碼(不是簡單的for循環while循環UIApplicationMain函數一直沒有返回,不斷地接收處理消息以及等待休眠,因此運行程序以後,會保持持續運行狀態git

RunLoop結構體

  • Source1 : 基於Port的線程間通訊
  • Source0 : 觸摸事件、PerformSelector
  • Timer : 定時器
  • Observer : 監聽器,用於監聽RunLoop的狀態

RunLoop和線程

  • 線程和RunLoop是一一對應的,其映射關係是保存在一個全局的Dictionary裏,線程做爲keyRunLoop做爲value
  • 本身建立的線程默認是沒有開啓RunLoop
  • runloop在第一次獲取時被建立,在線程結束時被銷燬
  • 對於主線程來講,runloop在程序一啓動就默認建立好了
  • 對於子線程來講,runloop是懶加載的,只有當咱們使用的時候纔會建立,因此在子線程用定時器要注意:確保子線程的runloop被建立,否則定時器不會回調
  1. 怎麼建立一個常駐線程
  • 爲當前線程開啓一個RunLoop(第一次調用[NSRunLoop currentRunLoop]方法時,實際是會先去建立一個RunLoop
  • 向當前RunLoop中添加一個Port/Source等維持RunLoop的事件循環(若是RunLoopmode中一個item都沒有,RunLoop會退出)
  • 啓動該RunLoop
@autoreleasepool {
  NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
  [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
  [runLoop run];
}
複製代碼
  1. 輸出下邊代碼的執行順序
NSLog(@"1");

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  NSLog(@"3");
});

NSLog(@"4");

- (void)test{
  NSLog(@"5");
}
複製代碼

答案是1423test方法並不會執行 緣由是:若是是帶afterDelay的延時函數,會在內部建立一個NSTimer,而後添加到當前線程的RunLoop中,也就是若是當前線程沒有開啓RunLoop,該方法會失效 那麼咱們改爲:github

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [[NSRunLoop currentRunLoop] run];
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  NSLog(@"3");
});
複製代碼

test方法依然不執行 緣由是:若是RunLoopmode中一個item都沒有,RunLoop會退出 即在調用RunLooprun方法後,因爲其mode中沒有添加任何item去維持RunLoop的事件循環,RunLoop隨即仍是會退出,因此咱們本身啓動RunLoop,必定要在添加itembash

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  NSLog(@"2");
  [self performSelector:@selector(test) withObject:nil afterDelay:10];
  [[NSRunLoop currentRunLoop] run];
  NSLog(@"3");
});
複製代碼

附:個人博客地址async

相關文章
相關標籤/搜索