美文网首页
使用GCD来创建Timer

使用GCD来创建Timer

作者: guoguojianshu | 来源:发表于2021-08-19 14:39 被阅读0次

推荐使用GCD方式创建timer的原因,GCD是基于内核的,会更加准时,NSTimer和CADisplayLink依赖于RunLoop,如果Runloop的任务太繁重,可能会导致NSTimer不准时

GCD的Timer创建

//stong修饰,强引用
@property (nonatomic,strong) dispatch_source_t timer;
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"begin");
    // Do any additional setup after loading the view.
//    队列
//   dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
//    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_queue_t queue = dispatch_get_main_queue();
//    创建定时器
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//    设置时间
//    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//    设置时间,带有延时几秒后执行的开启定时器的参数
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC), 1*NSEC_PER_SEC, 0);
//    设置回调
    dispatch_source_set_event_handler(timer, ^{
//        上面设置为什么队列,这个回调就在什么队列里面执行
        NSLog(@"执行定时器");
        NSLog(@"%@",[NSThread currentThread]);
    });
//   启动定时器
    dispatch_resume(timer);
//    设置timer为强引用的,否则不会执行,出了函数调用栈,就销毁了
    self.timer  = timer;
}

封装一个timer对象

.h


@interface JGTimer : NSObject
//开始定时器的方法
+(NSString *)execTask:(void(^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async;
//取消定时器
+(void)cancleTask:(NSString *)name;
@end

.m

#import "JGTimer.h"

@implementation JGTimer

//使用字典来表示,任务的名字和timer一一对应的关系,设置一个全局的字典
static NSMutableDictionary * timers_;
//使用信号量来解决多线程,同时操作字典的情况
dispatch_semaphore_t semaphore_ ;

// 使用initialize和单例初始化字典,因为只有给这个类发送消息时候来回调用这个方法
+(void)initialize{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        timers_ = [NSMutableDictionary dictionary];
        semaphore_ = dispatch_semaphore_create(1);
    });
}
+(NSString *)execTask:(void(^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async{
    if (!task || start < 0 || (interval <= 0 && repeats)) {
        return nil;
    }
    __weak typeof(self) weakSelf = self;

    dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0) : dispatch_get_main_queue();
//    创建定时器
 dispatch_source_t timer =   dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//    设置时间
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0);
    dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
    //    设置任务的名字
        NSString * name = [NSString stringWithFormat:@"%lu",(unsigned long)timers_.count];
    //    给定时器增加强引用,并且是任务的名字和定时器一一对应
    timers_[name] = timer;
    dispatch_semaphore_signal(semaphore_);
//    设置回调
    dispatch_source_set_event_handler(timer, ^{
        task();
//        如果取消这个任务,执行一次就取消
        if (!repeats) {
            [weakSelf cancleTask:name];
        }
    });
//    启动
    dispatch_resume(timer);
    return name;
}
+(void)cancleTask:(NSString *)name{
    if (name.length == 0) {
        return;
    }
    dispatch_source_t timer = timers_[name];
    if (!timer) return;
//    如果信号的值为1的话,会自动减1,然后执行下面的代码,如果这个值为0,就会休眠等待,直到这个值大于0时候,才会唤醒和继续执行
    dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
//    取消定时器
    dispatch_source_cancel(timers_[name]);
//    从字典中删除这个定时器,删除强引用
    [timers_ removeObjectForKey:name];
//    信号的值+1操作
    dispatch_semaphore_signal(semaphore_);
}

使用封装的定时器

- (void)viewDidLoad {
    [super viewDidLoad];
    /*
    NSLog(@"begin");
//    队列
//   dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
//    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_queue_t queue = dispatch_get_main_queue();
//    创建定时器
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//    设置时间
//    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//    设置时间,带有延时几秒后执行的开启定时器的参数
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC), 1*NSEC_PER_SEC, 0);
//    设置回调
    dispatch_source_set_event_handler(timer, ^{
//        上面设置为什么队列,这个回调就在什么队列里面执行
        NSLog(@"执行定时器");
        NSLog(@"%@",[NSThread currentThread]);
    });
//   启动定时器
    dispatch_resume(timer);
//    设置timer为强引用的,否则不会执行,出了函数调用栈,就销毁了
    self.timer  = timer;
    
    */
    
    
    
    
    
//   封装timer
    NSLog(@"begin");
   self.task =  [JGTimer execTask:^{
        NSLog(@"111");
    } start:2 interval:1 repeats:YES async:YES];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//    取消定时器
    [JGTimer cancleTask:self.task];
}

相关文章

  • 使用GCD来创建Timer

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

  • MQTT-Client-Framework GCD 使用

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

  • GCD timer

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

  • iOS多线程--彻底学会多线程之『GCD』

    GCD 文章目录 GCD简介 任务和队列 GCD的使用步骤 队列的创建方法 任务的创建方法 GCD的基本使用 并行...

  • Swift - GCD timer使用

    timer:https://github.com/100mango/SwiftTimer定时器:https://g...

  • iOS多线程--GCD篇

    GCD 文章目录GCD简介任务和队列GCD的使用步骤队列的创建方法任务的创建方法GCD的基本使用并行队列 + 同步...

  • GCD定时器

    GCD定时器的使用 self.timer = dispatch_source_create(DISPATCH_SO...

  • Timer的使用

    Timer创建 使用 scheduledTimerWithTimeInterval:invocation:repe...

  • GCD实现timer

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

  • NSTimer的简单介绍

    我们使用 NSTimer 来创建 timer 对象。一个 timer 对象等待一段时间间隔之后就会触发,发送一个消...

网友评论

      本文标题:使用GCD来创建Timer

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