定时器Timer的使用

时间:2021-03-18 23:26:57

//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