IOS开发入门之iOS中的计时器
凌雪 2018-11-09 来源 :网络 阅读 1289 评论 0

摘要:本文将带你了解IOS开发入门iOS中的计时器,希望本文对大家学IOS有所帮助。

本文将带你了解IOS开发入门iOS中的计时器,希望本文对大家学IOS有所帮助。


         

iOS中的计时器,NSTimer很方便,但是在很多场合下计时不准确。即使现在网上说烂了的把NSTimer加到runloop然后设置runloopmode,还是会出现不准确的情况。

比如视频播放的时候,有一种情况,主动从摄像头拉流,拉去频率为自己控制   。runloop里面也是排队执行,NSTimer在特定的时间点触发一次。在处理较多的任务时候,忙于应付,就不会触发这个周期的tick,等到下个周期再触发。所以导致计时不准确。

GCD   Timer

GCD   Timer用的人比较少,但是真心比NSTimer准确。GCD是基于C语言封装的,相对于NSTimer更底层一些,在网上查的关于GCD Timer的实现   从NSTimer的失效性谈起(二):关于GCD Timer和libdispatch

下面贴上GCD Timer的示例



dispatch_queue_t queue =   dispatch_get_global_queue(0,   0);

 

self.timer =   dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,   queue);

 

//开始时间

dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW,   3.0   *   NSEC_PER_SEC);

 

//间隔时间

uint64_t interval = 2.0 *   NSEC_PER_SEC;

 

 

dispatch_source_set_timer(self.timer, start, interval,   0);

 

//设置回调

dispatch_source_set_event_handler(self.timer,   ^{

 

    NSLog(@"----self.timer---");

});

 

 

//启动timer

dispatch_resume(self.timer);

   

和一些注意事项,来自Dispatch   Source Timer 的使用以及注意事项

Dispatch Source Timer 是一种与 Dispatch   Queue 结合使用的定时器。当需要在后台 queue 中定期执行任务的时候,使用 Dispatch Source Timer 要比使用 NSTimer   更加自然,也更加高效(无需在 main queue 和后台 queue 之前切换)。
创建 Timer
Dispatch   Source Timer 首先其实是 Dispatch Source 的一种,关于 Dispatch Source   的内容在这里就不再赘述了。下面是苹果官方文档里给出的创建 Dispatch Timer 的代码:


   

dispatch_source_t CreateDispatchTimer(uint64_t   interval,

              uint64_t   leeway,

              dispatch_queue_t   queue,

              dispatch_block_t   block)

{

   dispatch_source_t timer =   dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,

                                                     0, 0, queue);

   if (timer)

   {

      dispatch_source_set_timer(timer,   dispatch_walltime(NULL, 0),   interval, leeway);

      dispatch_source_set_event_handler(timer,   block);

      dispatch_resume(timer);

   }

   return timer;

}

   

有几个地方需要注意:
1.   Dispatch Source Timer 是间隔定时器,也就是说每隔一段时间间隔定时器就会触发。在 NSTimer 中要做到同样的效果需要手动把   repeats 设置为 YES。
2. dispatch_source_set_timer 中第二个参数,当我们使用   dispatch_time 或者 DISPATCH_TIME_NOW 时,系统会使用默认时钟来进行计时。然而当系统休眠的时候,默认时钟是不走的,也就会导致计时器停止。使用   dispatch_walltime 可以让计时器按照真实时间间隔进行计时。
3. dispatch_source_set_timer   的第四个参数 leeway 指的是一个期望的容忍时间,将它设置为 1 秒,意味着系统有可能在定时器时间到达的前 1 秒或者后 1   秒才真正触发定时器。在调用时推荐设置一个合理的 leeway 值。需要注意,就算指定 leeway 值为   0,系统也无法保证完全精确的触发时间,只是会尽可能满足这个需求。
4. event handler block 中的代码会在指定的   queue 中执行。当 queue 是后台线程的时候,dispatch timer 相比 NSTimer 就好操作一些了。因为 NSTimer 是需要   Runloop 支持的,如果要在后台 dispatch queue 中使用,则需要手动添加 Runloop。使用 dispatch timer   就简单很多了。
5. dispatch_source_set_event_handler 这个函数在执行完之后,block   会立马执行一遍,后面隔一定时间间隔再执行一次。而 NSTimer 第一次执行是到计时器触发之后。这也是和 NSTimer   之间的一个显著区别。
停止 Timer
停止 Dispatch Timer 有两种方法,一种是使用   dispatch_suspend ,另外一种是使用 dispatch_source_cancel 。
dispatch_suspend   严格上只是把 Timer 暂时挂起,它和 dispatch_resume 是一个平衡调用,两者分别会减少和增加 dispatch   对象的挂起计数。当这个计数大于 0 的时候,Timer 就会执行。在挂起期间,产生的事件会积累起来,等到 resume   的时候会融合为一个事件发送。
需要注意的是,dispatch source 并没有提供用于检测 source 本身的挂起计数的   API,也就是说外部不能得知一个 source 当前是不是挂起状态,在设计代码逻辑时需要考虑到这一点。
dispatch_source_cancel   则是真正意义上的取消 Timer。被取消之后如果想再次执行 Timer,只能重新创建新的 Timer。这个过程类似于对 NSTimer 执行   invalidate 。
关于取消 Timer,另外一个 很重要 的注意事项, dispatch_suspend 之后的   Timer,是不能被释放的!下面的代码会引起崩溃:


- (void)stopTimer

{

    dispatch_suspend(_timer);

    _timer = nil; // EXC_BAD_INSTRUCTION   崩溃

}

   

因此使用   dispatch_suspend 时,Timer 本身的实例需要一直保持。使用 dispatch_source_cancel 则没有这个限制:


   

- (void)stopTimer

{

    dispatch_source_cancel(_timer);

    _timer = nil; // OK

}

   

    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!

本文由 @凌雪 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved