iOS简单易用的GCD计时器的实现原理

前言

好久没更新文章了,在掘金第一次发文章,还是给自己立一个flag每周至少更新一篇文章,可能文章的质量还不是很如意,希望通过写文章来提高自己文笔,以及记录自己学习中的遇到的问题解决方案。

在学习iOS过程中,想定大家对于定时器都不陌生,在日常开发中总会碰到需要计时器的功能,常见的定时器有NSTimer、GCD、CADisplayLink。网上也有很多的教程介绍三者的区别,今天主要讲的是GCD这种方式使用以及封装。

三者概括区别

优点 缺点
NSTimer 使用简单 受Runloop影响会导致计时不精准
CADisplayLink 精度高      CPU负载的时候会影响触发事件,且触发事件大于触发间隔会导致掉帧现象。
GCD 较精准 代码较多,基本不受其他影响

总结:NSTimer和CADisplayLink易受影响,而GCD虽然代码多,但是可控性非常强。

GCD

/** 获取一个全局的线程来运行计时器*/
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/** 创建一个计时器*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
/** 设置计时器, 这里是每10毫秒执行一次*/
dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), 10*NSEC_PER_MSEC, 0);
/** 设置计时器的里操作事件*/
dispatch_source_set_event_handler(timer, ^{
 //do you want....
});

开启、继续已暂停的定时器

dispatch_resume(timer);

暂停定时器

/** 挂起的时候注意,多次暂停的操作会导致线程锁的现象,即多少次暂停,
*  对应多少次的继续操作,即dispatch_suspend和dispatch_resume
*  是成对出现的,计时器才会继续工作。
*/
dispatch_suspend(timer);

结束定时器

dispatch_source_cancel(timer);

构思封装

写代码之前构思好功能模块以及会遇到的问题的解决方案、代码逻辑,再来下手写代码,会有事半功倍的效果。

  • 必然包含开始、暂停、继续、停止、重置功能
  • 时间计算过程中因浮点数计算会丢失精度,计算过程应采用NSDecimal
  • 时间转换考虑到精度以及便利性,采用系统的时间转换方法,时区置为GMT
  • 由于APP进入后台,若未开启后台任务的开关,计时器将会停止,再次进入APP又会继续,故采用监听app状态的方式记录APP进入后台与前台的时间戳,并与截止时间相比,是否继续计时还是结束计时并回调。
  • 计时器返回的结果若采用字符串则还需处理,故使用了一个时间类来把结果返回,可以进行自定义操作
  • 倒计时的结果返回和结束通知采用闭包形式

部分代码

/** app进入后台*/
- (void)appDidEnterBackground{
  [self suspend];
  NSDate *date = [[NSDate alloc] init];
  NSDateFormatter *format = [[NSDateFormatter alloc] init];
  format.dateFormat = @"yyyy-MM-dd HH:mm:ss:SSS";
  self.appDidEnterBackgroundTime = [date timeIntervalSince1970];
}

/** app进入前台*/
- (void)appDidEnterForeground{
  NSDate *date = [[NSDate alloc] init];
  NSDateFormatter *format = [[NSDateFormatter alloc] init];
  format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
  self.appDidEnterForegroundTime = [date timeIntervalSince1970];
  [self reCalculateMinder];
}

/** 不失精度加减乘除计算结果*/

- (NSDecimalNumber *)value: (NSTimeInterval)value
        byOpration: (OMDecimalOprationType)byOpration
         percision: (NSInteger)percision
        withValue: (NSTimeInterval)withValue{

  NSDecimalNumber *number = [self numberValueWithString: value];
  NSDecimalNumber *withNumber = [self numberValueWithString: withValue];
  NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode: NSRoundPlain scale: percision raiseOnExactness: NO raiseOnOverflow: NO raiseOnUnderflow: NO raiseOnDivideByZero: YES];

switch (byOpration) {
  case OMDecimalOprationTypeAdd:
   return [number decimalNumberByAdding: withNumber withBehavior:handler];
   break;
  case OMDecimalOprationTypeSubtract:
   return [number decimalNumberBySubtracting: withNumber withBehavior: handler];
   break;
  case OMDecimalOprationTypeDivide:
   return [number decimalNumberByDividingBy: withNumber withBehavior: handler];
   break;
 case OMDecimalOprationTypeMultiple:
   return [number decimalNumberByMultiplyingBy: withNumber withBehavior: handler];
   break;
 default:
   break;
   return nil;
}
@property (nonatomic, strong) OMTimer *timer;
self.timer = [[OMTimer alloc] init];
self.timer.timerInterval = 30;
self.timer.precision = 100;
self.timer.isAscend = NO;
self.timer.progressBlock = ^(OMTime *progress) {
   NSLog(@"%@:%@:%@:%@", progress.hour, progress.minute, progress.second, progress.millisecond;
};self.timer.completion = ^{
  NSLog(@"complete done!");
};

Swift版本

最近喜欢上了OC,如有小伙伴需要Swift的版本的话可以留言或者私我,可以在写个Swift版本,:stuck_out_tongue_winking_eye:。

结语

使用简单,只需要把OMTimer.h和OMTimer.m拖入你的工程即可,满足大数的场景,可倒计时亦可增加计时,全部代码已在Github<https://github.com/oymuzi/OMKit/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详细整理iOS中UITableView的性能优化

    一.介绍 iOS开发中,UITableView可能是平时我们打交道最多的UI控件之一,其重要性不言而喻.Android也是如此,Android中的ListView和UITableView是相同功能的一个控件,但是iOS的UITableView更为强大一点,原因就不说了,如果你学过Android就知道iOS中的UITableView使用起来是非常简单的,这也是峰哥喜欢iOS胜过Android的原因之一.今天研究的内容就是UITableView的优化. 开始之前,你能说出几种UITableView的

  • iOS实现UITableView数据为空时的提示页面

    前言 相信对于iOS开发者们来说,在开发过程中,经常用UITableView,一定会遇到数据为空的情况,这时需要在空页面上放一个图片和一行文字提示数据为空,下面整理了两种方法来实现这个功能. 第一个是继承UITableView,在新类中集成图片和文字 #import <UIKit/UIKit.h> #import "Const.h" @interface WFEmptyTableView : UITableView @property (nonatomic, assign)

  • iOS 11 下适配UITableView 问题

    9月份苹果发布了IOS11和Iphone X,这一操作系统一硬件对于开发者适配上面还是造作了不少蛋疼的地方.先来看看IOS 11,这些蛋疼的需要适配的地方: 1.UIScrollView及其子类在IOS 11之前的版本UI显示完全正常,但是在IOS 11上面会显示奇葩的界面. (1)先看一下UITablevIew. 原本在VC里面的automaticallyAdjustsScrollViewInsets竟然过期了,在IOS 11下 APPLE推荐使用UIScrollView的contentIns

  • iOS应用进入后台后计时器和位置更新停止问题的解决办法

    由于iOS系统为"伪后台"运行模式,当按下HOME键时,如程序不做任何操作,应用会有5秒的执行缓冲时间,随机程序被挂起,所有任务终端,包括计时器和位置更新等操作,但程序打开后台模式开关后,部分任务可以再后台执行,如音频,定位,蓝牙,下载,VOIP,即便如此,程序的后台运行最多可以延长594秒(大概是10分钟).不幸的是,程序在声明后台模式后很有可能在app上架时被拒.基于此,我研究出了不用申明后台模式就能让计时器和定位在app进入前台时继续运行的方法.   实现原理如下: 利用iOS的

  • iOS之UITableView计时器的实现方式总结(NSTimer、DispatchSource、CADisplayLink)

    前言 最近工作比较忙,但是还是出来更新博客了.今天博客中所涉及的内容并不复杂,都是一些平时常见的一些问题,通过这篇博客算是对UITableView中使用定时器的几种方式进行总结.本篇博客会给出在TableView中使用NSTimer或者DispatchSourcer中常见的五种方式.当然下方第一种方式是常规做法,不过也是UITableView中使用NSTimer的一个坑.其他三种方式是为了绕过这个坑的解决方案. 当然,本篇博客共涉及到了UITableView中使用定时器的四种实现方式,当然应该也

  • IOS中UITableView滚动到指定位置

    方法很简单: - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated 有些需要注意的地方: 如果在reloadData后需要立即获取tableview的cell.高度,或者需要滚动tableview,那么,直接在reloadData后执行代码是有可能出问题的. reloadDa

  • iOS中的UITableView的重用机制与加载优化详解

    UITableView可以说是UIKit中最重要的一个组件,用来展示数据列表,还可以灵活使用进行页面的布局.UITableView的使用遵循MVC模式,数据模型(NSObject).视图(UIView)和控制器(UITableViewController)分离.UITableView继承自UIScrollView,可上下滑动,可以作为跟视图也可以作为子视图组件. reuseIdentifier顾名思义是一个复用标识符,是一个自定义的独一无二的字符串,用来唯一地标记某种重复样式的可复用UITabl

  • 详解iOS开发中UItableview控件的数据刷新功能的实现

    实现UItableview控件数据刷新 一.项目文件结构和plist文件 二.实现效果 1.说明:这是一个英雄展示界面,点击选中行,可以修改改行英雄的名称(完成数据刷新的操作). 运行界面: 点击选中行: 修改数据后自动刷新: 三.代码示例 数据模型部分: YYheros.h文件 复制代码 代码如下: // //  YYheros.h //  10-英雄展示(数据刷新) // //  Created by apple on 14-5-29. //  Copyright (c) 2014年 itc

  • iOS简单易用的GCD计时器的实现原理

    前言 好久没更新文章了,在掘金第一次发文章,还是给自己立一个flag每周至少更新一篇文章,可能文章的质量还不是很如意,希望通过写文章来提高自己文笔,以及记录自己学习中的遇到的问题解决方案. 在学习iOS过程中,想定大家对于定时器都不陌生,在日常开发中总会碰到需要计时器的功能,常见的定时器有NSTimer.GCD.CADisplayLink.网上也有很多的教程介绍三者的区别,今天主要讲的是GCD这种方式使用以及封装. 三者概括区别 优点 缺点 NSTimer 使用简单 受Runloop影响会导致计

  • iOS实现高性能简单易用的星星评分控件

    前言 做为老司机的你们有没有遇到过这样的需求?每个商品或者商家的item都有个星级或者其他评分,大概像以下的效果图 实现方案: 大神自己写个通用空间(在时间充足的情况下) 网上找个比较好的第三方 (时间比较紧凑的情况下) 更直接的,自己直接放几个ImageView或者Layer 思考:功能是实现了,但是性能好像有点受影响.具体原因要看第三方框架的实现原理,当然了也有做的很好的.我是个性能控,当我拿到这个需求的时候,也尝试用一些第三方,但结果不尽人意.最后XWStarView就此产生了. XWSt

  • 简单易扩展可控性强的Jquery转盘抽奖程序

    基于Jquery的Javascript转盘抽奖程序,可以自定义抽奖界面,奖品数量.图片等,可控制中奖的奖品,抽奖转盘转动的速度和圈数. 在实际使用中,应当把概率放到后台程序中运算,以保证安全性和产生中奖奖品的可控性 Javascript代码: <script type="text/javascript"> var index = 1, //当前亮区位置 prevIndex = 14, //前一位置 Speed = 300, //初始速度 Time, //计时器 arr_le

  • 简单易用的倒计时js代码

    <!doctype html> <html> <head> <meta charset="utf-8"> <title>简单易用的倒计时js代码</title> <style> *{ margin:0; padding:0; list-style:none;} body{ font-size:18px; text-align:center;} .time{ height:30px; padding:20

  • 简单易用的基于jQuery版仿新浪微博向下滚动效果(附DEMO)

    简单易用的jQuery 写的仿新浪微博 向下滚动效果 $(function(){ var scrtime; $("#con").hover(function(){ clearInterval(scrtime); },function(){ scrtime = setInterval(function(){ var $ul = $("#con ul"); var liHeight = $ul.find("li:last").height(); $u

  • IOS 简单的本地json格式文件解析的实例详解

    IOS 简单的本地json格式文件解析的实例详解 ljweibo.json文件 { "data":[{ "name" : "孙悟空", "content" : "7月12日的国务院常务会议上,李克强明确要求,要将已审议的<快递条例(草案)>向社会公开征求意见.在会上,总理说了这么一段话:"几年前,快递业刚刚开始发展的时候,有些城市不允许快递存在,理由是影响市容整洁,快递员骑的摩的也不允许停放.但

  • IOS简单实现瀑布流UICollectionView

    UICollectionView 比tableView 灵活,功能也强大很多.系统实现了流式布局,但用处还有很多限制. 要想实现更灵活的布局,就咬重写UICollectionViewLayout. 先看下实现效果: 废话不多说,直接上代码: 先看WaterfallCollectionLayout.m #import "WaterfallCollectionLayout.h" #define colMargin 5 #define colCount 4 #define rolMargin

  • 基于JS代码实现简单易用的倒计时 x 天 x 时 x 分 x 秒效果

    废话不多说了,直接给大家贴代码了,具体代码如下所示: <script> (function () { var tian = document.getElementsByClassName('JS-tian')[0]; var shi = document.getElementsByClassName('JS-shi')[0]; var fen = document.getElementsByClassName('JS-fen')[0]; var miao = document.getEleme

  • JS实现简单易用的手机端浮动窗口显示效果

    本文实例讲述了JS实现简单易用的手机端浮动窗口显示效果.分享给大家供大家参考,具体如下: html: <style type="text/css"> .fdBonTel{ width:100%; height:53px; position:fixed; background:#0052ae; text-align:center; left:0; bottom:0; z-index:999; } .fdOnline{ background:url(index/images/o

  • 新版VPS主机管理面板WDCP安装及使用体验-国产简单易用型VPS面板

    WDCP也算是国产中颇受大家欢迎的VPS主机面板了,提供了nginx.apache.mysql.php等Web建站环境一键搭建.印象中,国内VPS主机面板也就是WDCP还在坚持着,AMH已经走上了收费的道路(PS:免费版本长年不更新,各种问题和不兼容). 而WDCP实际上也有长达几年的时间没有更新了,mysql.php版本都停留好早以前的版本,新出来的一直都没有更新, 已经不能满足于现在的Wordpress建站需要了,这也是部落为什么要扔掉VPS面板!网站平滑迁移到LNMP或LAMP建站. 好在

随机推荐