美文网首页
GCD定时器

GCD定时器

作者: 小罗哦吧 | 来源:发表于2019-08-28 16:26 被阅读0次

    NSTimer 因为runloop的原因会导致不准确。
    所以我们可以用GCD定时器

    // 队列
        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, 2 * NSEC_PER_SEC),
                                  2 * NSEC_PER_SEC, 0);
      dispatch_source_set_event_handler(timer, ^{
            //做事情
        });
    // 启动定时器
        dispatch_resume(timer);
    

    确实很简单 我们封装下吧
    .h如下

    /**
     定时器开启
    
     @param task 任务
     @param start 开始时间
     @param interval 几秒执行一次
     @param repeats 是否重复
     @param async 那个线程
     @return ——
     */
    + (NSString *)execTask:(void(^)(void))task
               start:(NSTimeInterval)start
            interval:(NSTimeInterval)interval
             repeats:(BOOL)repeats
               async:(BOOL)async;
    //关掉定时器 name:定时器唯一标识
    + (void)cancelTask:(NSString *)name;
    

    .m

    static NSMutableDictionary *timers_;
    dispatch_semaphore_t semaphore_;
    + (void)initialize
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            timers_ = [NSMutableDictionary dictionary];//用于存放定时器,以便用来拿到定时器
            semaphore_ = dispatch_semaphore_create(1);
        });
    }
    /**
     定时器开启
     
     @param task 任务
     @param start 开始时间
     @param interval 几秒执行一次
     @param repeats 是否重复
     @param async 那个线程
     @return ——
     */
    +(NSString *)execTask:(void(^)(void))task
                    start:(NSTimeInterval)start
                 interval:(NSTimeInterval)interval
                 repeates:(BOOL)repeats
                    async:(BOOL)async{
        
        if (!task || start < 0 || (interval <= 0 && repeats)) return nil;
        
        // 队列
        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:@"%zd", timers_.count];
        // 存放到字典中
        timers_[name] = timer;
        dispatch_semaphore_signal(semaphore_);
        
        // 设置回调
        dispatch_source_set_event_handler(timer, ^{
            task();
    
            if (!repeats) { // 不重复的任务
                [self cancelTask:name];
            }
        });
      
        // 启动定时器
        dispatch_resume(timer);
        
        return name;
        
        
    }
    
    + (void)cancelTask:(NSString *)name
    {
        if (name.length == 0) return;
        
        dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);//加锁 因为可能多个线程访问字典
        
        dispatch_source_t timer = timers_[name];
        if (timer) {
            dispatch_source_cancel(timer);
            [timers_ removeObjectForKey:name];
        }
        
        dispatch_semaphore_signal(semaphore_);
    }
    

    然后就可以在外部调用

    相关文章

      网友评论

          本文标题:GCD定时器

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