iOS dispatch_source_t 定时器

前言

NSTimer受runloop的影响,由于runloop需要处理很多任务,导致NSTimer的精度降低,在日常开发中,如果我们需要对定时器的精度要求很高的话,可以考虑dispatch_source_t去实现 。dispatch_source_t精度很高,系统自动触发,系统级别的源

代码

__block int timeout=30; //倒计时时间
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
    
    //开始的时间
    dispatch_time_t startTime = dispatch_walltime(NULL, 1.0 * NSEC_PER_SEC);
    //间隔的时间
    uint64_t interval = 1.0 * NSEC_PER_SEC;
    
    dispatch_source_set_timer(_timer,startTime,interval, 0); //每秒执行
    dispatch_source_set_event_handler(_timer, ^{
        
        if(timeout<=0){ //倒计时结束,关闭
            dispatch_source_cancel(_timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                //设置界面的按钮显示 根据自己需求设置
                
            });
        }else{
            //            int minutes = timeout / 60;
            int seconds = timeout % 60;
            NSString *strTime = [NSString stringWithFormat:@"%.2d", seconds];
            dispatch_async(dispatch_get_main_queue(), ^{
                //设置界面的按钮显示 根据自己需求设置
                NSLog(@"____%@",strTime);
                
            });
            timeout--;
        }
    });
    //启动定时器
    dispatch_resume(_timer);

解析开始的时间

dispatch_time_t 类型,它的创建有两个函数
     1. dispatch_time(<#dispatch_time_t when#>, <#int64_t delta#>)
        第一个参数是从什么时间开始,一般直接传 DISPATCH_TIME_NOW; 表示从现在开始
        第二个参数表示具体的时间长度(不能直接传 int 或 float), 可以写成这种形式 (int64_t)3* NSEC_PER_SEC
        
        #define NSEC_PER_SEC 1000000000ull  每秒有1000000000纳秒
        #define NSEC_PER_MSEC 1000000ull    每毫秒有1000000纳秒
        #define USEC_PER_SEC 1000000ull     每秒有1000000微秒
        #define NSEC_PER_USEC 1000ull       每微秒有1000纳秒
        
        注意 delta 的单位是纳秒! 
        1秒的写作方式可以是 1* NSEC_PER_SEC; 1000* NSEC_PER_MSEC; USEC_PER_SEC* NSEC_PER_USEC
     
     2. dispatch_walltime(<#const struct timespec * _Nullable when#>, <#int64_t delta#>),
        第一个参数是一个结构体, 创建的是一个绝对的时间点,比如 2016年10月10日8点30分30秒, 如果你不需要自某一个特定的时刻开始,可以传 NUll,表示自动获取当前时区的当前时间作为开始时刻, 第二参数意义同第一个函数
        dispatch_time_t time = dispatch_walltime(NULL, 5* NSEC_PER_SEC);
        
     两个函数的不同
       例如: 从现在开始,1小时之后是触发某个事件
       使用第一个函数创建的是一个相对的时间,第一个参数开始时间参考的是当前系统的时钟,当 device 进入休眠之后,系统的时钟也会进入休眠状态, 第一个函数同样被挂起; 假如 device 在第一个函数开始执行后10分钟进入了休眠状态,那么这个函数同时也会停止执行,当你再次唤醒 device 之后,该函数同时被唤醒,但是事件的触发就变成了从唤醒 device 的时刻开始,1小时之后
       而第二个函数则不同,他创建的是一个绝对的时间点,一旦创建就表示从这个时间点开始,1小时之后触发事件,假如 device 休眠了10分钟,当再次唤醒 device 的时候,计算时间间隔的时间起点还是 开始时就设置的那个时间点, 而不会受到 device 是否进入休眠影响
参考文章

http://blog.csdn.net/wpeng20125/article/details/73650569
http://blog.csdn.net/cuichengjie/article/details/45912809

你可能感兴趣的:(iOS dispatch_source_t 定时器)