一、介绍

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

二、使用

  1. @property (strong,nonatomic)NSTimer *timer;
  2. @property (strong,nonatomic)CADisplayLink *displaylinkTimer;
  3. @property (strong,nonatomic)dispatch_source_t sourceTimer;

1、NSTimer:

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

解释:

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

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

特性:

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

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

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

2、CADisplayLink:

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

解释:

当把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:

  1. //dispatch_source_t
  2. -(void)createDispatch_source_t{
  3.  
  4. //创建全局队列
  5. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
  6.  
  7. //使用全局队列创建计时器
  8. _sourceTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, , , queue);
  9.  
  10. //定时器延迟时间
  11. NSTimeInterval delayTime = 1.0f;
  12.  
  13. //定时器间隔时间
  14. NSTimeInterval timeInterval = 1.0f;
  15.  
  16. //设置开始时间
  17. dispatch_time_t startDelayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC));
  18.  
  19. //设置计时器
  20. dispatch_source_set_timer(_sourceTimer,startDelayTime,timeInterval*NSEC_PER_SEC,0.1*NSEC_PER_SEC);
  21.  
  22. //执行事件
  23. dispatch_source_set_event_handler(_sourceTimer,^{
  24.  
  25. //销毁定时器
  26. //dispatch_source_cancel(_myTimer);
  27. });
  28.  
  29. //启动计时器
  30. dispatch_resume(_sourceTimer);
  31. }

特性:

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

重要属性:

  1. dispatch_source_set_timer(dispatch_source_t source,
  2. dispatch_time_t start,
  3. uint64_t interval,
  4. 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. 002.NFS相关配置项

    一 配置文件(/etc/exports) 1.1 配置文件格式 <输出目录> [客户端1 选项(访问权限,用户映射,其他)] [客户端2 选项(访问权限,用户映射,其他)] 二 输出目录 ...

  2. IE8及以下浏览器伪数组slice方法兼容处理

    前几天同事说数组的slice方法在IE8下有兼容问题,我查阅了MDN,文档里面有提到IE8及以下浏览器中,DOM对象组成的伪数组通过call调用slice方法没有遵循标准行为 我做了个demo在IE8 ...

  3. Java日期时间类

    日期时间类有三种: 一.java.util.Date:一般用于声明日期时间类型的变量. 二.java.sql.Date:一般用于数据库日期时间的映射. 三.java.util.Calendar:一般用 ...

  4. Codeforces-1077C

    title: Codeforces-1077C date: 2018-11-24 15:22:31 tags: acm 刷题 categories: Codeforces 题意 题目链接 给你一个数组 ...

  5. 安装redis出现的问题

    这个问题是我在腾讯云上安装redis时出现的错误, 1.在执行make命令时出现的错误 解决方案,没有安装gcc 什么是gcc: GCC是一个用于linux系统下编程的编译器是一个用于编程开发的自由编 ...

  6. Struts2拦截器详解

    一.Struts2拦截器原理: Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的    拦截器对象,然后串成一个列 ...

  7. Xamarin iOS教程之键盘的使用和设置

    Xamarin iOS教程之键盘的使用和设置 Xamarin iOS使用键盘 在文本框和文本视图中可以看到,当用户在触摸这些视图后,就会弹出键盘.本节将主要讲解键盘的输入类型定义.显示键盘时改变输入视 ...

  8. windows系统,联系人文件。个性化。

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha ======= 文件下载链接:

  9. BZOJ3518 : 点组计数

    若直线的斜率为0或者不存在斜率,则有$nC(m,3)+mC(n,3)$种方案.若直线的斜率不为0,只需考虑斜率为正的情况,最后答案再乘以2即可.枚举两个点的坐标差,设$t=\min(n,m)$,则有: ...

  10. 20172308《Java软件结构与数据结构》第三周学习总结

    教材学习内容总结 第 5 章 队列 队列: 一种线性集合,其元素从一端加入,从另一端删除 元素处理:FIFO 与栈的比较 异:(1) 栈的处理过程只在栈的某一端进行:队列的处理过程在队列的两端进行.( ...