经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
iOS简单易用的GCD计时器的实现原理
来源:jb51  时间:2018/11/27 9:57:35  对本文有异议

前言

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

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

三者概括区别

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

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

GCD

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

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

  1. dispatch_resume(timer);

暂停定时器

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

结束定时器

  1. dispatch_source_cancel(timer);

构思封装

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

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

部分代码

  1. /** app进入后台*/
  2. - (void)appDidEnterBackground{
  3. [self suspend];
  4. NSDate *date = [[NSDate alloc] init];
  5. NSDateFormatter *format = [[NSDateFormatter alloc] init];
  6. format.dateFormat = @"yyyy-MM-dd HH:mm:ss:SSS";
  7. self.appDidEnterBackgroundTime = [date timeIntervalSince1970];
  8. }
  9.  
  10. /** app进入前台*/
  11. - (void)appDidEnterForeground{
  12. NSDate *date = [[NSDate alloc] init];
  13. NSDateFormatter *format = [[NSDateFormatter alloc] init];
  14. format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
  15. self.appDidEnterForegroundTime = [date timeIntervalSince1970];
  16. [self reCalculateMinder];
  17. }
  18.  
  19. /** 不失精度加减乘除计算结果*/
  20.  
  21. - (NSDecimalNumber *)value: (NSTimeInterval)value
  22. byOpration: (OMDecimalOprationType)byOpration
  23. percision: (NSInteger)percision
  24. withValue: (NSTimeInterval)withValue{
  25.  
  26. NSDecimalNumber *number = [self numberValueWithString: value];
  27. NSDecimalNumber *withNumber = [self numberValueWithString: withValue];
  28. NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode: NSRoundPlain scale: percision raiseOnExactness: NO raiseOnOverflow: NO raiseOnUnderflow: NO raiseOnDivideByZero: YES];
  29.  
  30. switch (byOpration) {
  31. case OMDecimalOprationTypeAdd:
  32. return [number decimalNumberByAdding: withNumber withBehavior:handler];
  33. break;
  34. case OMDecimalOprationTypeSubtract:
  35. return [number decimalNumberBySubtracting: withNumber withBehavior: handler];
  36. break;
  37. case OMDecimalOprationTypeDivide:
  38. return [number decimalNumberByDividingBy: withNumber withBehavior: handler];
  39. break;
  40. case OMDecimalOprationTypeMultiple:
  41. return [number decimalNumberByMultiplyingBy: withNumber withBehavior: handler];
  42. break;
  43. default:
  44. break;
  45. return nil;
  46. }
  47.  
  1. @property (nonatomic, strong) OMTimer *timer;
  1. self.timer = [[OMTimer alloc] init];
  2. self.timer.timerInterval = 30;
  3. self.timer.precision = 100;
  4. self.timer.isAscend = NO;
  5. self.timer.progressBlock = ^(OMTime *progress) {
  6. NSLog(@"%@:%@:%@:%@", progress.hour, progress.minute, progress.second, progress.millisecond;
  7. };self.timer.completion = ^{
  8. NSLog(@"complete done!");
  9. };

Swift版本

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

结语

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

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号