1.runloop的作用 :
? ? 保證程序不退出
? ? 負責事件的監聽,時鐘(定時器)/觸摸事件/網絡事件
? ? 當沒有事件發生的時候,會讓程序進入休眠狀態
? ? 渲染屏幕上的點
2.runloop的對象
? ? Foundation框架里面有NSRunloop,
? ? [NSRunLoop currentRunLoop];//獲取當前線程的runloop對象
? ? [NSRunLoop mainRunLoop];//獲取主線程的runloop對象
? ? Core Foundation里面有CFRunloopRef
? ? CFRunLoopGetCurrent();//獲取主線程的runloop對象
? ? CFRunLoopGetMain();//獲取主線程的runloop對象
? ? 其中NSRunloop是基于CFRunloopRef加一層OC的封裝。
3.runloop的modes
? ? 1.UIInitializationRunLoopMode,剛啟動app調用的mode,完成后不在使用.
? ? 2.GSEventReceiveRunLoopMode,接受系統事件的內部mode,用不到。
? ?3.NSDefaultRunLoopMode,默認mode,蘋果建議將時鐘還有網絡添加到這個mode
? 4.UITrackingRunLoopMode,處理UI的mode,并保證在交互時不受其他mode影響
? ———NSRunLoopCommonModes,是一種占位mode。。。使用這個mode會在需要的時候在NSDefaultRunLoopMode跟UITrackingRunLoopMode來回占位,保證在兩種mode中都運行不受影響。
4.runloop處理的事件
? ?1.CFRunLoopSourceRef 事件輸入源,
? ? ? ? ?source0:用于用戶主動觸發事件(非系統事件)
? ? ? ? ?source1:通過內核和其它線程相互發送消息,系統事件
? 2.CFRunLoopObserverRef ——runloop的觀察者
/**
? ?runloop的活動觀察
? ? ?kCFRunLoopEntry = (1UL << 0),進入runloop
? ? ?kCFRunLoopBeforeTimers = (1UL << 1),處理timer前
? ? ?kCFRunLoopBeforeSources = (1UL << 2),處理source前
? ? kCFRunLoopBeforeWaiting = (1UL << 5),休眠前
? ? kCFRunLoopAfterWaiting = (1UL << 6),休眠后
? ? kCFRunLoopExit = (1UL << 7),退出
? ? kCFRunLoopAllActivities = 0x0FFFFFFFU 所有事件
*/
? ? // 創建一個監聽者
? ? ? CFRunLoopObserverRef observer = ?CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, ? YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
? ? ? ? ? ? ? NSLog(@"%ld",activity);
? ?});
? ?// 給runloop添加監聽者
? ? CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
? ? // 釋放runloop
? ? CFRelease(observer);
3.CFRunLoopTimerRef——基于時間的觸發器
NSTimer * timer1 = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self ? ? selector:@selector(updataTimer) userInfo:nil repeats:YES];
使用上面方法創建timer會自動加入runloop,但是模式是默認的NSDefaultRunLoopMode(蘋果建議將時鐘加入此mode)。所以在于界面交互時timer會停止,故而輪播圖常常需要使用下面的方法創建定時器
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updataTimer) userInfo:nil repeats:YES];//不會自動加入runloop,需要手動加入
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];//這是死循環,故而經常單獨寫一個子線程
CGD的定時器不受runloop影響
//創建隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//創建定時器
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//設置定時器
dispatch_time_t interval = 1.0 * NSEC_PER_SEC;//時間間隔
dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, interval, 0);
//設置事件
dispatch_source_set_event_handler(self.timer, ^{
? ? ? ?NSLog(@"%@------",[NSThread currentThread]);
});
//啟動定時器
dispatch_resume(self.timer);