//Runloop
主线程的Runloop默认开启,不需要再去启动。
子线程的Runloop需要手动开启。
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong)NSTimer *timer;
@property (nonatomic , strong) dispatch_source_t gcdTimer;
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self timer2];
}
-(void)timer1 {
//这个方法创建的定时器需要加到 runloop中,并且会受到mode的影响,运行模式为NSDefaultRunLoopMode时,刷新界面时定时器会停止。
运行模式为UITrackingRunLoopMode时,刷新界面时定时器才会运行。(界面跟踪模式)
如果运行模式是NSRunLoopCommonMode时, 默认是以上两种模式下,定时器都会运行。
// _timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
// [[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];
// [[NSRunLoop currentRunLoop]run];主线程不需要这一行,主线程调动这一行,会出现问题。
//使用这个方法创建定时器,scheduled方法会在内部自动将定时器加到Runloop中,默认使用NSDefaultRunLoopMode模式。
_timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop]run];
}
可以看出NSTimer会受到Runloop运行模式的影响,NSTimer定时器是不准确的,
-(void)timer2 {
//如果在项目中需要使用准确的计时器,最好使用GCD定时器,是准确的,GCD定时器的单位是纳秒,精确度高。
下面代码每2秒调用一次,最后一个参数传0表示不允许误差。dispatch_source_t需要强引用。
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
[self run];
});
dispatch_resume(timer);
self.gcdTimer = timer;
}
-(void)run {
NSLog(@"-------run-----%@",[NSThread currentThread]);
}
@end