在开发的过程当中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的模式的影响.
网友评论