一、介绍

在iOS中,计时器是比较常用的,用于统计累加数据或者倒计时等,例如手机号获取验证码。计时器大概有那么三种,分别是:NSTimer、CADisplayLink、dispatch_source_t

二、使用

@property (strong,nonatomic)NSTimer *timer;
@property (strong,nonatomic)CADisplayLink *displaylinkTimer;
@property (strong,nonatomic)dispatch_source_t sourceTimer;

1、NSTimer:

//NSTimer
-(void)createTimer{ //初始化
//_timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
//执行操作
//}]; _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerStart:) userInfo:nil repeats:YES]; //加入runloop循环池
[[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode]; //开启定时器
[_timer fire];
}
-(void)timerStart:(NSTimer *)timer{
NSLog(@"%s-----%lf",__func__,timer.timeInterval); //销毁定时器
//[_timer invalidate];
//_timer = nil;
}

解释:

  • TimerInterval: 执行之前等待的时间。比如设置成1.0,就代表1秒后执行方法
  • target: 需要执行方法的对象。
  • selector : 需要执行的方法
  • repeats : 是否需要循环

注意 :
调用创建方法后,target对象的计数器会加1,直到执行完毕,自动减1。如果是循环执行的话,就必须手动关闭,否则可以不执行释放方法。

特性:

  • 存在延迟
  • 不管是一次性的还是周期性的timer的实际触发事件的时间,都会与所加入的RunLoop和RunLoop Mode有关,如果此RunLoop正在执行一个连续性的运算,timer就会被延时出发。重复性的timer遇到这种情况,如果延迟超过了一个周期,则会在延时结束后立刻执行,并按照之前指定的周期继续执行。
  • 必须加入Runloop

使用上面的创建方式,会自动把timer加入MainRunloop的NSDefaultRunLoopMode中。如果使用以下方式创建定时器,就必须手动加入Runloop:

NSTimer *timer = [NSTimer timerWithTimeInterval: target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

2、CADisplayLink:

//CADisplayLink
-(void)createCADisplayLink{ _displaylinkTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
[_displaylinkTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
-(void)handleDisplayLink:(CADisplayLink *)displaylinkTimer{
NSLog(@"%s-----%ld",__func__,displaylinkTimer.preferredFramesPerSecond); //销毁定时器
//[_displaylinkTimer invalidate];
//_displaylinkTimer = nil;
}

解释:

当把CADisplayLink对象add到runloop中后,selector就能被周期性调用,类似于重复的NSTimer被启动了;执行invalidate操作时,CADisplayLink对象就会从runloop中移除,selector调用也随即停止,类似于NSTimer的invalidate方法。

特性:

  • 屏幕刷新时调用CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CADisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。所以通常情况下,按照iOS设备屏幕的刷新率60次/秒
  • 延迟iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。但如果调用的方法比较耗时,超过了屏幕刷新周期,就会导致跳过若干次回调调用机会。如果CPU过于繁忙,无法保证屏幕60次/秒的刷新率,就会导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度。

使用场景:

  • 从原理上可以看出,CADisplayLink适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染。

重要属性:

  • frameInterval(已过时,用preferredFramesPerSecond替代)  NSInteger类型的值,用来设置间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。
  • duration  readOnly的CFTimeInterval值,表示两次屏幕刷新之间的时间间隔。需要注意的是,该属性在target的selector被首次调用以后才会被赋值。selector的调用间隔时间计算方式是:调用间隔时间 = duration × frameInterval。

3、dispatch_source_t:

//dispatch_source_t
-(void)createDispatch_source_t{ //创建全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); //使用全局队列创建计时器
_sourceTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, , , queue); //定时器延迟时间
NSTimeInterval delayTime = 1.0f; //定时器间隔时间
NSTimeInterval timeInterval = 1.0f; //设置开始时间
dispatch_time_t startDelayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC)); //设置计时器
dispatch_source_set_timer(_sourceTimer,startDelayTime,timeInterval*NSEC_PER_SEC,0.1*NSEC_PER_SEC); //执行事件
dispatch_source_set_event_handler(_sourceTimer,^{ //销毁定时器
//dispatch_source_cancel(_myTimer);
}); //启动计时器
dispatch_resume(_sourceTimer);
}

特性:

  • 默认是重复执行的,可以在事件响应回调中通过dispatch_source_cancel方法来设置为只执行一次,如下代码:
dispatch_source_set_event_handler(_timer, ^{
//执行事件
dispatch_source_cancel(_timer);}
);

重要属性:

dispatch_source_set_timer(dispatch_source_t source,
dispatch_time_t start,
uint64_t interval,
uint64_t leeway);
  • start计时器起始时间,可以通过dispatch_time创建,如果使用DISPATCH_TIME_NOW,则创建后立即执行
  • interval计时器间隔时间,可以通过timeInterval * NSEC_PER_SEC来设置,其中,timeInterval为对应的秒数
  • leeway这个参数的理解,我觉得http://www.dreamingwish.com上Seven's同学的解释很直观也很易懂:“这个参数告诉系统我们需要计时器触发的精准程度。所有的计时器都不会保证100%精准,这个参数用来告诉系统你希望系统保证精准的努力程度。如果你希望一个计时器没五秒触发一次,并且越准越好,那么你传递0为参数。另外,如果是一个周期性任务,比如检查email,那么你会希望每十分钟检查一次,但是不用那么精准。所以你可以传入60,告诉系统60秒的误差是可接受的。这样有什么意义呢?简单来说,就是降低资源消耗。如果系统可以让cpu休息足够长的时间,并在每次醒来的时候执行一个任务集合,而不是不断的醒来睡去以执行任务,那么系统会更高效。如果传入一个比较大的leeway给你的计时器,意味着你允许系统拖延你的计时器来将计时器任务与其他任务联合起来一起执行。

优点:

  • 时间准确
  • 可以使用子线程,解决定时间跑在主线程上卡UI问题

注意事项:

  • 需要将dispatch_source_t timer设置为成员变量,不然会立即释放

三、参考原链接:

http://www.jianshu.com/p/53c07eb57223

iOS:三种常见计时器(NSTimer、CADisplayLink、dispatch_source_t)的使用的更多相关文章

  1. iOS开发--计时器-NSTimer与CADisplayLink

    如果程序要让某个方法重复执行,可以借助定时器来完成.CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器,NSTimer的精确度低了点,比如NSTimer的触发时间 ...

  2. 浅析NSTimer & CADisplayLink内存泄露

    偶得前言 NSRunLoop与定时器 - invalidate的作用 我们如何解决? 偶得前言 本篇文章中我们主要谈谈NSTimer\CADisplayLink在使用过程中牵扯到内存泄露的相关问题及解 ...

  3. 深入学习jQuery的三种常见动画效果

    × 目录 [1]显隐效果 [2]高度变化 [3]淡入淡出 前面的话 动画效果是jQuery吸引人的地方.通过jQuery的动画方法,能够轻松地为网页添加视觉效果,给用户一种全新的体验.jQuery动画 ...

  4. Android应用开发中三种常见的图片压缩方法

    Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩). 一.质量压缩法 private Bitmap com ...

  5. 三种常见的部署Kubernetes的方式

    三种常见的部署Kubernetes的方式 嘹亮的小号 Ghostcloud-001工号,资深Docker玩家,分布式系统研发11年. ​关注他   容器技术将应用程序及其依赖关系与操作系统进行分离,不 ...

  6. Spring源码分析之IOC的三种常见用法及源码实现(二)

    Spring源码分析之IOC的三种常见用法及源码实现(二) 回顾上文 我们研究的是 AnnotationConfigApplicationContext annotationConfigApplica ...

  7. iOS开发中深入理解CADisplayLink和NSTimer

    一.什么是CADisplayLink 简单地说,它就是一个定时器,每隔几毫秒刷新一次屏幕. CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器.我们在应用中创建一 ...

  8. ios 中定时器:NSTimer, CADisplayLink, GCD

    #import "ViewController.h" #import "RunloopViewController.h" @interface ViewCont ...

  9. 【转】IOS 计时器 NSTimer

    原文网址:http://blog.csdn.net/tangshoulin/article/details/7644124 1.初始化 + (NSTimer *)timerWithTimeInterv ...

随机推荐

  1. 把.html转换成.jsp中jqplot画图表不能正常显示,出错的心得

    在做这个的时候,明明html中是完全可行的,如下图: 但后缀名改成.jsp后竟出现如下情况: 这太坑爹了吧,我的图呢! 哎,又要自己找代码问题了,无奈! 先给出我还没修改前的代码吧,关于里面的.js, ...

  2. PBR Step by Step(四)Lambertian反射模型

    光照可分为局部光照和全局光照. 局部光照:直接照射到物体表面的光照 全局光照:物体表面受周围环境影响的光照 左图中点x接收到周围环境的光线照射,来自周围表面的反射光照称为全局光照:右图中点x接收来自太 ...

  3. 使用Google-Colab训练PyTorch神经网络

    Colaboratory 是免费的 Jupyter 笔记本环境,不需要进行任何设置就可以使用,并且完全在云端运行.关键是还有免费的GPU可以使用!用Colab训练PyTorch神经网络步骤如下: 1: ...

  4. C# 实现IDisposable的模式

    来自MSDN官方文档:http://msdn.microsoft.com/en-us/library/system.configuration.provider.providercollection. ...

  5. .net core在Linux ARM板上运行

    最近接了个临时任务,给别的项目组的机器人平台上开发个小程序,那机器人上跑的是ARM平台,ubuntu的系统. 本来打算用C++写的,由于最近用.net core较多,鉴于其在linux平台良好的兼容性 ...

  6. LightOJ 1118 - Incredible Molecules (两圆面积交)

    1118 - Incredible Molecules   PDF (English) Statistics Forum Time Limit: 0.5 second(s) Memory Limit: ...

  7. STM32 通用定时器的几种配置方式

    STM32 通用定时器的几种配置方式 //------------------------------------------------------------------------------ ...

  8. Overclock STM32F4 device up to 250MHz

    http://stm32f4-discovery.com/2014/11/overclock-stm32f4-device-up-to-250mhz/ Let’s test what STM32F4x ...

  9. TextAppearance.Material.Widget.Button.Inverse,Widget.Material.Button.Colored

    编译xamarin android项目报错: android:TextAppearance.Material.Widget.Button.Inverse android:Widget.Material ...

  10. 关于GPL协议的理解(开源与商用、免费与收费的理解)

    编者:请特别注意看暗红色粗体标注的那几句话,总结下来有下面几点: 如果你用了我的 GPL软件,那么你的软件也必须要开源,否则就不能使用我的软件,你是否把你的软件商用和我没关系 Oracle 卖的不是软 ...