一:RunLoop相關類:
其中:source0指的是非基於端口por,說白了也就是處理觸摸事件,selector事件,source1指的是基於端口的port:是處理系統的一些事件
注意:創建一個RunLoop之后,有默認的運行模式mode,也可以為RunLoop指定運行模式,RunLoop啟動必須得有運行模式,而且在運行模式中必須還有timer或是source事件其中之一,否則RunLoop就會退出。啟動RunLoop必須調用start方法
二:RunLoop運行處理邏輯
RunLoop通知觀察者Observer即將進入RunLoop,此時通知觀察者Observer處理Timer,通知觀察者Observer處理source0(非基於端口port,也就是觸摸,滾動,selector選擇器事件),此時RunLoop會處理source0事件,當處理完source0事件后,如果此時沒有source1(系統事件)則RunLoop進入休眠狀態,直到外部的source0,timer或是外部手動喚醒RunLoop,若是此時有source1事件,則會處理喚醒時受到的消息,之后再繼續跳回2--處理timer--處理source0--在檢查有無source1 ,RunLoop就是一個死循環,最后如果線程被掛掉(也就是線程中的任務執行完畢后,線程就會掛掉,即使使用外部強引用指向該線程,線程依然會掛掉,若是想使線程執行完任務后,不被掛掉,則可以手動開啟RunLoop,為RunLoop指定運行模式mode,在mode中必須為RunLoop指定source或是timer,否則RunLoop會立即退出,)會通知Observer即將退出RunLoop
2:蘋果官方版
#import "ViewController.h" /** * 1:為RunLoop添加監聽者:1:先創建監聽者 2:添加監聽者 */ @interface ViewController () /** 注釋 */ //@property (nonatomic, strong) pthread_t thread; @end @implementation ViewController #pragma mark ---------------------- #pragma mark Events -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // [self observer]; // [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(task) userInfo:nil repeats:YES]; [NSThread detachNewThreadSelector:@selector(task) toTarget:self withObject:nil]; } - (IBAction)sourceBtnClick:(id)sender { NSLog(@"%s",__func__); } #pragma mark ---------------------- #pragma mark -(void)task { NSLog(@"%s",__func__); // [NSRunLoop currentRunLoop] runUntilDate:[]; } -(void)observer { //1.創建監聽者 /* 第一個參數:怎么分配存儲空間 第二個參數:要監聽的狀態 kCFRunLoopAllActivities 所有的狀態 第三個參數:時候持續監聽 第四個參數:優先級 總是傳0 第五個參數:當狀態改變時候的回調 */ 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; } }); /* 第一個參數:要監聽哪個runloop 第二個參數:觀察者 第三個參數:運行模式 */ CFRunLoopAddObserver(CFRunLoopGetCurrent(),observer, kCFRunLoopDefaultMode); //NSDefaultRunLoopMode == kCFRunLoopDefaultMode //NSRunLoopCommonModes == kCFRunLoopCommonModes } @end