GCD-dispatch_source以及自定义倒计时GCD-dispatch_source以及自定义倒计时

2021-08-09 11:09:05 浏览数 (2)

1、简述

dispatch_source是基础数据类型,用于协调特定底层系统事件的处理。

  • dispatch_source替代了异步回调函数,来处理系统相关的事件,当配置一个dispatch时,你需要指定监测的事件dispatch queue、以及处理事件的代码(block或函数)`。当事件发生时,dispatch source会提交你的block或函数到指定的queue去执行
  • 使用 Dispatch Source 而不使用 dispatch_async 的唯一原因就是利用联结的优势
  • 联结的大致流程为:在任一线程上调用它的一个函数dispatch_source_merge_data后,会执行Dispatch Source事先定义好的句柄(可以把句柄简单理解为一个block),这个过程叫 Custom event(用户事件)。是 dispatch source 支持处理的一种事件。
    • 简单来说:这种事件是由你调用 dispatch_source_merge_data 函数来向自己发出的信号。
  • 特点
    1. 其CPU负荷非常小,金陵不占用资源
    2. 结的优势

2、使用

2.1 创建dispatch源
代码语言:javascript复制
dispatch_source_t source = dispatch_source_create(dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t queue)
2.1.1 参数说明
2.1.2 Dispatch Source 种类

image.png

2.1.3 注意
  • DISPATCH_SOURCE_TYPE_DATA_ADD 当同一时间,一个事件的的触发频率很高,那么Dispatch Source会将这些响应以ADD的方式进行累积,然后等系统空闲时最终处理,如果触发频率比较零散,那么Dispatch Source会将这些事件分别响应;
  • DISPATCH_SOURCE_TYPE_DATA_OR 自定义的事件,但是它是以OR的方式进行累积;
2.2 常用函数
代码语言:javascript复制
//挂起队列
dispatch_suspend(queue) 

//分派源创建时默认处于暂停状态,在分派源分派处理程序之前必须先恢复
dispatch_resume(source) 

//向分派源发送事件,需要注意的是,不可以传递0值(事件不会被触发),同样也不可以传递负数。
dispatch_source_merge_data 

//设置响应分派源事件的block,在分派源指定的队列上运行
dispatch_source_set_event_handler 

//得到分派源的数据
dispatch_source_get_data 

//得到dispatch源创建,即调用dispatch_source_create的第二个参数
uintptr_t dispatch_source_get_handle(dispatch_source_t source); 

//得到dispatch源创建,即调用dispatch_source_create的第三个参数
unsigned long dispatch_source_get_mask(dispatch_source_t source); 

////取消dispatch源的事件处理--即不再调用block。如果调用dispatch_suspend只是暂停dispatch源。
void dispatch_source_cancel(dispatch_source_t source); 

//检测是否dispatch源被取消,如果返回非0值则表明dispatch源已经被取消
long dispatch_source_testcancel(dispatch_source_t source); 

//dispatch源取消时调用的block,一般用于关闭文件或socket等,释放相关资源
void dispatch_source_set_cancel_handler(dispatch_source_t source, dispatch_block_t cancel_handler); 

//可用于设置dispatch源启动时调用block,调用完成后即释放这个block。也可在dispatch源运行当中随时调用这个函数。
void dispatch_source_set_registration_handler(dispatch_source_t source, dispatch_block_t registration_handler); 

3、倒计时器

代码语言:javascript复制
- (void)demo{
    //倒计时时间
    __block int timeout = 3;
    
    //创建队列
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    
    //创建timer
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, globalQueue);
    
    //设置1s触发一次,0s的误差
    /*
     - source 分派源
     - start 数控制计时器第一次触发的时刻。参数类型是 dispatch_time_t,这是一个opaque类型,我们不能直接操作它。我们得需要 dispatch_time 和 dispatch_walltime 函数来创建它们。另外,常量 DISPATCH_TIME_NOW 和 DISPATCH_TIME_FOREVER 通常很有用。
     - interval 间隔时间
     - leeway 计时器触发的精准程度
     */
    dispatch_source_set_timer(timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0);
    
     //触发的事件
    dispatch_source_set_event_handler(timer, ^{
        //倒计时结束,关闭
        if (timeout <= 0) {
            //取消dispatch源
            dispatch_source_cancel(timer);
        }else{
            timeout--;
            
            dispatch_async(dispatch_get_main_queue(), ^{
                //更新主界面的操作
                NSLog(@"倒计时 - %d", timeout);
            });
        }
    });
    
    //开始执行dispatch源
    dispatch_resume(timer);
}

转载自: Style_月月

0 人点赞