【iOS沉思录】如何创建NSTimer并使其在当前线程中正常运行?
2018-02-01 10:30
549 查看
NSTimer主要用于开启定时任务,但要真确使用才能保证其正常有效运行。尤其要注意以下两点:
确保NSTimer已经添加到当前RunLoop;
确保当前RunLoop已经启动。
这两种方法的主要区别为,使用timerWithTimeInterval创建的timer不会自动添加到当前RunLoop中,需要手动添加并制定RunLoop的模式:[[NSRunLoop currentRunLoop] addTimer:mainThreadTimer forMode:NSDefaultRunLoopMode]; 而使用scheduledTimerWithTimeInterval创建的RunLoop会默认自动添加到当前RunLoop中。
NSTimer只有添加到启动起来的RunLoop中才会正常运行。NSTimer通常不建议添加到主线程中执行,因为界面的更新在主线程中,界面导致的卡顿会影响NSTimer的准确性。
以下为四种情形下正确的使用方法:
打印结果为:
NSTimer的释放方法:
确保NSTimer已经添加到当前RunLoop;
确保当前RunLoop已经启动。
1.创建NSTimer有两种方法:
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo; + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
这两种方法的主要区别为,使用timerWithTimeInterval创建的timer不会自动添加到当前RunLoop中,需要手动添加并制定RunLoop的模式:[[NSRunLoop currentRunLoop] addTimer:mainThreadTimer forMode:NSDefaultRunLoopMode]; 而使用scheduledTimerWithTimeInterval创建的RunLoop会默认自动添加到当前RunLoop中。
2.NSTimer可能在主线程中创建,也可能在子线程中创建:
主线程中的RunLoop默认是启动的,所以timer只要添加到主线程RunLoop中就会被执行;而子线程中的RunLoop默认是不启动的,所以timer添加到子线程RunLoop中后,还要手动启动RunLoop才能使timer被执行。NSTimer只有添加到启动起来的RunLoop中才会正常运行。NSTimer通常不建议添加到主线程中执行,因为界面的更新在主线程中,界面导致的卡顿会影响NSTimer的准确性。
以下为四种情形下正确的使用方法:
- (void)viewDidLoad { [super viewDidLoad]; /* 主线程中创建timer */ NSTimer *mainThreadTimer = [NSTimer timerWithTimeInterval:10.0 target:self selector:@selector(mainThreadTimer_SEL) userInfo:nil repeats:YES]; NSTimer *mainThreadSchduledTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(mainThreadSchduledTimer_SEL) userInfo:nil repeats:YES]; /* 将mainThreadTimer1添加到主线程runloop */ [[NSRunLoop currentRunLoop] addTimer:mainThreadTimer forMode:NSDefaultRunLoopMode]; /* 子线程中创建timer */ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSTimer *subThreadTimer = [NSTimer timerWithTimeInterval:10.0 target:self selector:@selector(subThreadTimer_SEL) userInfo:nil repeats:YES]; NSTimer *subThreadSchduledTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(subThreadSchduledTimer_SEL) userInfo:nil repeats:YES]; /* 将subThreadTimer1添加到子线程runloop */ [[NSRunLoop currentRunLoop] addTimer:subThreadTimer forMode:NSDefaultRunLoopMode]; /* 启动子线程runloop */ [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; }); } - (void) mainThreadTimer_SEL{ NSLog(@"mainThreadTimer is working!"); } - (void) mainThreadSchduledTimer_SEL{ NSLog(@"mainThreadSchduledTimer is working!"); } - (void) subThreadTimer_SEL{ NSLog(@"subThreadTimer is working!"); } - (void) subThreadSchduledTimer_SEL{ NSLog(@"subThreadSchduledTimer is working!"); }
打印结果为:
2018-01-31 20:24:10.729259+0800 IOSDemo[41891:4382661] mainThreadSchduledTimer is working! 2018-01-31 20:24:20.728351+0800 IOSDemo[41891:4382661] mainThreadTimer is working! 2018-01-31 20:24:20.728409+0800 IOSDemo[41891:4382720] subThreadTimer is working! 2018-01-31 20:24:20.728693+0800 IOSDemo[41891:4382720] subThreadSchduledTimer is working!
NSTimer的释放方法:
[timer invalidate];
相关文章推荐
- 如何创建并运行java线程
- 【iOS-cocos2d-X 游戏开发之四】Cocos2dX创建Android NDK新项目并编译导入Eclipse中正常运行!
- iOS开发——创建你自己的Framework && IOS如何在当前工程中导入另一个工程文件
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- 如何创建并运行Java线程
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- iOS 在子线程运行performSelector和NSTimer
- 如何创建并运行java线程
- 【iOS-cocos2d-X 游戏开发之四】Cocos2dX创建Android NDK新项目并编译导入Eclipse中正常运行! 推荐
- Java并发编程学习笔记(五)如何创建并运行java线程
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- Android异步通信机制简单地理解,Handler是当前线程的消息队列中的一个子队列,而Runable是可以被安排到Handler去运行的接口。 首先在Activity中创建一个继承自Han
- 如何创建并运行 java 线程
- 如何创建并运行java线程
- 如何创建并运行 java 线程
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
- 如何创建并运行Java线程
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行