美文网首页美文共赏
ios 使用GCD定时器

ios 使用GCD定时器

作者: Victory_886 | 来源:发表于2021-11-25 15:28 被阅读0次

    定时器我们首先想到是NSTimer,不过NSTimer 有的时候会不准确,那么怎么处理呢?
    因为NSTimer 是在Runloop 中,runloop 也是一个跑圈,一圈回来的时间不确定所以导致NSTimer 不准确;而GCD 是系统内核中的,滑动也不收到影响。面试也容易被问到这个。

    下面来看看代码:

    
    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);
        });
    }
    
    
    
    // 返回一个 字符串 标记为任务id 方便定时器随时停止
    + (NSString *)execStart:(NSTimeInterval)start
                   interval:(NSTimeInterval)interval
                    repeats:(BOOL)repeats
               isMainThread:(BOOL)async
                       task:(void (^)(void))task {
        
        if (!task || start < 0 || (interval <=0 && repeats)) return nil;
        
        dispatch_queue_t queue = async ? dispatch_get_main_queue() : dispatch_get_global_queue(0, 0);
        
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        
        // 字典操作的时候加一个锁处理
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        NSString *name = [NSString stringWithFormat:@"%zd",timers.count];
        timers[name] = timer;
        
        dispatch_semaphore_signal(semaphore);
    
        dispatch_source_set_timer(timer,
                                  dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC),
                                  interval * NSEC_PER_SEC, 0);
        
        dispatch_source_set_event_handler(timer, ^{
            
            task();
            if (!repeats) {
                
                // 不重复的任务
                [self cancelTak:name];
            }
        });
        
        dispatch_resume(timer);
        return name;
    }
    
    /// 取消定时任务
    + (void)cancelTak:(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);
    }
    
    

    项目中要是使用到就拿回去用用吧,我也是自己简单封装了一下,也有优化的余地根据需求修改吧~

    相关文章

      网友评论

        本文标题:ios 使用GCD定时器

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