GCD定时器

在开发的过程当中NSTimer是一个比较常用的类,用来计时,但是NSTimer有时候不准确,原因很简单,主要受Runloop模式的影响.

   [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(update) userInfo:nil repeats:YES];

这样写默认在runloop的NSDefaultRunLoopMode模式下工作,如果runloop的模式切换到其他模式,NSTimer就会停止工作,切换回到NSDefaultRunLoopMode模式下的时候又继续工作,所以会导致不准确.

解决方案:

方案一:
将NSTimer添加到kCFRunLoopCommonModes模式下,不管runloop的模式是NSDefaultRunLoopMode模式下工作还是在UITrackingRunLoopMode模式下工作都不会影响到定时器的工作.

 NSTimer *timer =   [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(test) userInfo:nil repeats:YES];
 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
 

方案二:使用GCD,因为GCD不受runloop的模式影响.
具体实现见下面的代码:

//
//  ViewController.m
//  GCD定时器
//
//  Created by zhaodajun on 16/7/27.
//  Copyright © 2016年 zhaodajun. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, assign) int count;
/**  定时器 */
@property (nonatomic, strong) dispatch_source_t timer;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //1.获取队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    //创建一个定时器
    //dispatch_source_t本质上还是一个OC对象
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    //设置一些参数
    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
    uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);
    
    dispatch_source_set_timer(self.timer, start, interval, 0);
    
    //设置回调
    dispatch_source_set_event_handler(self.timer, ^{
        _count++;
        NSLog(@"%d",_count);
        
        if (_count > 4) {
            //取消定时器
            dispatch_source_cancel(self.timer);
            self.timer = nil;
        }
    });
    dispatch_resume(self.timer);
 
}

@end

运行后可以看到时间准确,并且不受runloop的模式的影响.

你可能感兴趣的:(GCD定时器)