在主线程中开启定时器
1. 方法一:
//该方法内部自动添加到runloop中,并且设置运行模式为默认(上一篇讲到运行模式有五种)
[NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @selector(run) userInfo: nil repeats: YES];
2. 方法二
//1.创建定时器
NSTimer * timer = [NSTimer timerWithTimeInterval: 2.0 target: self selector: @selector(run) userInfo: nil repeats: YES];
//2.添加定时器到runLoop中,指定runloop的运行模式为NSDefaultRunLoopMode
/*
第一个参数:定时器
第二个参数:runloop的运行模式
*/
[[NSRunLoop currentRunLoop] addTimer: timer forMode: NSDefaultRunLoopMode];
3. 问题:通过上面两个方法我们都能开启一个定时器,但是在某些情况下存在一定的问题.在一个控制器里面放一个 tableview,同时用上述开启一个定时器,你会发现在滚动 tableview 时,定时器不执行相应的方法.为什么?这是因为运行循环同时只能存在一种运行模式,当我们在滑动 tableview 时,运行循环的运行模式是 UITrackingRunLoopMode,而我们在定时器添加到了默认的模式下,所以在滑动 tableview 时定时器就失灵了.
解决方法:有一个运行模式是 kCFRunLoopCommonModes,这是一个占用,标签模式,怎么理解了,你可以认为就是 NSRunLoopCommonModes = NSDefaultRunLoopMode + UITrackingRunLoopMode.其实是在 NSDefaultRunLoopMode 和 UITrackingRunLoopMode 模式上都打上了 kCFRunLoopCommonModes 的标签.当你把定时器添加到 kCFRunLoopCommonModes 模式后,不管当前运行模式处于 NSDefaultRunLoopMode 模式 还是 处于 UITrackingRunLoopMode 模式,都会执行.
3.GCD 中的定时器
直接贴上某老师的代码,讲得很好
#import "ViewController.h"
@interface ViewController ()
/** 注释 */
@property (nonatomic, strong) dispatch_source_t timer;
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"%s",__func__);
//1.创建GCD中的定时器
/*
第一个参数:source的类型DISPATCH_SOURCE_TYPE_TIMER 表示是定时器
第二个参数:描述信息,线程ID
第三个参数:更详细的描述信息
第四个参数:队列,决定GCD定时器中的任务在哪个线程中执行
*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
//2.设置定时器(起始时间|间隔时间|精准度)
/*
第一个参数:定时器对象
第二个参数:起始时间,DISPATCH_TIME_NOW 从现在开始计时
第三个参数:间隔时间 2.0 GCD中时间单位为纳秒
第四个参数:精准度 绝对精准0
*/
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//3.设置定时器执行的任务
dispatch_source_set_event_handler(timer, ^{
NSLog(@"GCD---%@",[NSThread currentThread]);
});
//4.启动执行
dispatch_resume(timer);
self.timer = timer;
}
@end
来源: http://www.jianshu.com/p/20725f8199c3