之前在項目中遇見了一個問題,在子線程中如何開啟NSTimer和取消NSTimer。現(xiàn)在總結一下,當做自己的筆記。
1.子線程中NSTimer的開啟
首先在.m文件中聲明兩個屬性一個是子線程 一個是子線程中的NSTimer。
@property (nonatomic, strong) NSThread *thread1;
@property (nonatomic, strong) NSTimer *threadTimer;
然后用GCD在全局全隊中創(chuàng)建一個子線程并創(chuàng)建NSTimer。
__weak __typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
strongSelf.thread1 = [NSThread currentThread];
[strongSelf.thread1 setName:@"線程A"];
strongSelf.threadTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:strongSelf selector:@selector(timerAction) userInfo:nil repeats:YES];
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addTimer:strongSelf.threadTimer forMode:NSDefaultRunLoopMode];
[runloop run];
}
});
注意的是:在子線程中創(chuàng)建的NSTimer需要加入到對應線程的RunLoop中。RunLoop中常用的mode有:NSDefaultRunLoopMode、UITrackingRunLoopMode和NSRunLoopCommonModes三種模式。
NSDefaultRunLoop 默認模式
UITrackingRunLoop 界面追蹤,用于scrollView拖拽 滑動
NSRunLoopCommonModes 不是一個特定的模式,只是一種標記,比較綜合的一種模式(包含 前兩種模式)
在NSTimer加入RunLoop后,需要將RunLoop運行起來。
2.子線程中NSTimer的關閉
之后創(chuàng)建一個cancelTimer的方法
- (void)cancel{
if (self.threadTimer) {
[self.threadTimer invalidate];
self.threadTimer = nil;
}
}
如果這個方法跟創(chuàng)建NSTimer不在同一個線程執(zhí)行是無法將Timer 執(zhí)行invalidate操作的。
然后現(xiàn)在我們需要在thread1這個線程中執(zhí)行這個操作,在這里寫一個方法用于在子線程中調用此方法。
- (void)cancelTimer{
if (self.threadTimer && self.thread1) {
[self performSelector:@selector(cancel) onThread:self.thread1 withObject:nil waitUntilDone:YES];
}
}
最后我們在有需要關閉Timer的地方執(zhí)行此方法即可。
在這里說明一下為什么NSTimer要在同一個線程中創(chuàng)建和關閉。因為創(chuàng)建的Timer的時候已經把Timer加入到該線程對應的RunLoop中,這個RunLoop設置了這個Timer為一個事件。因此要在同一個線程中才能cancel這個Timer。