美文网首页
GCD的timer

GCD的timer

作者: gpylove | 来源:发表于2018-11-20 11:29 被阅读16次

#import "TestViewController.h"

@interface TestViewController ()

@property (nonatomic, strong) dispatch_source_t timer;

@end

@implementationTestViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view.

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

    dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), (uint64_t)(3*NSEC_PER_SEC), 0);

    dispatch_source_set_event_handler(self.timer, ^{

        NSLog(@"dispatch");

    });

    dispatch_resume(self.timer);

}

- (void)dealloc{

    dispatch_source_cancel(_timer);

}

@end

dispatch_source_create(,,,)

用于返回一个dispatch_source_t对象。第一个参数为源类型,最后一个参数为资源要加入的队列。中间两个参数没明白是干什么用的😭,所以都默认0。

dispatch_source_set_timer(,,,)

用来设置我们timer的相关信息。第一个参数是我们的timer对象,第二个是首次触发的延迟时间,第三个参数是触发的时间间隔,最后一个参数是触发的允许延迟值。其中第二个参数,当我们使用dispatch_time或者DISPATCH_TIME_NOW时,系统会使用默认时钟来进行计时。然而当系统休眠的时候,默认时钟是不走的,也就会导致计时器停止。使用dispatch_walltime可以让计时器按照真实时间间隔进行计时。

dispatch_source_set_event_handler(,)

用来设置timer的触发事件。第一个参数为timer对象,第二个为回调block。dispatch_source_set_event_handler()中的任务实在子线程中执行的,若需要回到主线程,要调用dispatch_async(dispatch_get_main_queue(), ^{}.

dispatch_resume()

激活源对象。新创建的timer必须激活才会执行。

dispatch_suspend()

暂停源对象。dispatch_suspend 暂停队列并不意味着当前执行的 block 暂停,调用 dispatch_suspend 暂停一个队列,并不意味着暂停当前正在执行的 block,而是 block 可以执行完,但是接下来的 block 会被暂停,直到 dispatch_resume 被调用。

dispatch_source_cancel()

销毁定时器。dispatch_source_cancel 则是真正意义上的取消 timer。被取消之后如果想再次执行 timer,只能重新创建新的 timer。这个过程类似于对 NSTimer 执行 invalidate。

需要注意的是,dispatch_source_t  一定要被设置为成员变量,否则将会立即被释放。

注意:暂停(dispatch_suspend)的timer,不能被释放的,会引起崩溃。

Calls to dispatch_suspend() must be balanced with calls to dispatch_resume().

dispatch_suspend 和 dispatch_resume 应该是成对出现的。两者分别会减少和增加 dispatch 对象的暂停计数,但是没有 API 获取当前是暂停还是执行状态,所以需要自己记录。你调用了suspend(暂停)几次,你想resume(恢复)的话,就必须要remuse(恢复)几次,才能继续运行。

所以建议控制器添加一个标识符,记录源是否处于暂停状态,在dealloc事件中判断当前源是否被暂停,如果被暂停,则resume,即可解决内存泄漏问题。

但是还有不一般的情况,如果暂停的代码加到 dispatch_source_set_event_handler 的 block 中,并不会发生崩溃,但是这个时候页面会无法释放造成内存泄漏。

dispatch_source_set_event_handler(timer, ^() {

  dispatch_suspend(self.timer);

});

其他注意事项:

1.但remuse(恢复)的状态下,如果再进行一次resume(恢复)就会crash,所以要注册一个BOOL值的状态进行记录,防止多次suspend和resume引起闪退。

2.在suspend(暂停)的状态下,如果你设置timer = nil就会crash。

3.在suspend(暂停)的状态下,即使调用dispatch_source_cancel也没用,会造成内存泄漏,甚至崩溃。

后记:

GCDTimer的优势:不受当前runloopMode的影响。

劣势:其计时效应仍不是百分之百准确的。另外,他的触发事件也有可能被阻塞,当GCD内部管理的所有线程都被占用时,其触发事件将被延迟。

相关文章

  • MQTT-Client-Framework GCD 使用

    GCDTimer 使用GCD 的 source timer 来完成 timer 做的事情. MQTTCFSocke...

  • iOS开发之进阶篇(10)—— Timer

    概述 本文将要讨论以下三种timer: NSTimer (Timer) CADisplayLink GCD 原理 ...

  • 不需要手动释放的IOS定时器

    1.GCD优点:调用 dispatch_source_cancel(timer); 就会将 timer 对象销毁,...

  • GCD timer

    1.GCD提供了一个类似于NSTimer的类:dispatch_source_t 这个类的特点: GCD的time...

  • GCD Timer

    倒计时 定时器 timer 循环执行定时器

  • GCD timer

    推荐使用GCD方式创建timer的原因,GCD是基于内核的,会更加准时,NSTimer和CADisplayLink...

  • GCD的timer

    #import "TestViewController.h"@interface TestViewControll...

  • 使用GCD来创建Timer

    推荐使用GCD方式创建timer的原因,GCD是基于内核的,会更加准时,NSTimer和CADisplayLink...

  • GCD之timer源码剖析

    参考:从NSTimer的失效性谈起(二):关于GCD Timer和libdispatch

  • GCD实现timer

    uint64_tinterval =2*NSEC_PER_SEC; //创建一个专门执行timer回调的GCD队列...

网友评论

      本文标题:GCD的timer

      本文链接:https://www.haomeiwen.com/subject/qaumfqtx.html