一. dispatch_source_t
这里当做是一个数据类型 而dispatch_source是负责监听事件
dispatch_source_create
从字面上不难理解create(创建)一个,第一个需要填的dispatch_source_type_t,也就是需要监听的类型有很多种如下:
1.DISPATCH_SOURCE_TYPE_DATA_ADD
2.DISPATCH_SOURCE_TYPE_DATA_OR
3.DISPATCH_SOURCE_TYPE_MACH_SEND
4.DISPATCH_SOURCE_TYPE_MACH_RECV
5.DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
6.DISPATCH_SOURCE_TYPE_PROC
7.DISPATCH_SOURCE_TYPE_READ
8.DISPATCH_SOURCE_TYPE_SIGNAL
9.DISPATCH_SOURCE_TYPE_TIMER
10.DISPATCH_SOURCE_TYPE_VNODE
11.DISPATCH_SOURCE_TYPE_WRITE
第二个参数需要填的是个什么?查了一下:在64位的机器上,intptr_t和uintptr_t分别是long int、unsigned long int的别名;在32位的机器上,intptr_t和uintptr_t分别是int、unsigned int的别名。但是这里填什么呢?打开api告诉这里填写一个句柄,一个常量.我又找到了如下的方法:
uintptr_t dispatch_source_get_handle(<#dispatch_source_t source#>)
DISPATCH_SOURCE_TYPE_DATA_ADD: n/a
DISPATCH_SOURCE_TYPE_DATA_OR: n/a
DISPATCH_SOURCE_TYPE_MACH_SEND: mach port (mach_port_t)
DISPATCH_SOURCE_TYPE_MACH_RECV: mach port (mach_port_t)
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE n/a
DISPATCH_SOURCE_TYPE_PROC: process identifier (pid_t)
DISPATCH_SOURCE_TYPE_READ: file descriptor (int)
DISPATCH_SOURCE_TYPE_SIGNAL: signal number (int)
DISPATCH_SOURCE_TYPE_TIMER: n/a
DISPATCH_SOURCE_TYPE_VNODE: file descriptor (int)
DISPATCH_SOURCE_TYPE_WRITE: file descriptor (int)
这让我很惊讶,n/a的含义不适用,process identifier是进程的id ,file descriptor 是文件的描述,signal number是信号编号,mach_port_t查api是mach端口的用户个人空间,搞不懂.但是搞清楚了 可以填3个值:MACH_PORT_NULL,MACH_PORT_DEAD,MACH_PORT_VALID(name),分别代表,没有任何端口或端口权限;有端口但是不能用;自定义的端口名字.
目前第二个参数我用到的都是直接填0.暂且留个坑,等以后弄明白了再加上.
第三个参数从api字面上的意思是指定需要哪些事件的标志掩码.输入一个常量控制.
同样有一个方法
dispatch_source_get_mask(dispatch_source_t source)
DISPATCH_SOURCE_TYPE_DATA_ADD: n/a
DISPATCH_SOURCE_TYPE_DATA_OR: n/a
DISPATCH_SOURCE_TYPE_MACH_SEND: dispatch_source_mach_send_flags_t
DISPATCH_SOURCE_TYPE_MACH_RECV: n/a
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE dispatch_source_memorypressure_flags_t
DISPATCH_SOURCE_TYPE_PROC: dispatch_source_proc_flags_t
DISPATCH_SOURCE_TYPE_READ: n/a
DISPATCH_SOURCE_TYPE_SIGNAL: n/a
DISPATCH_SOURCE_TYPE_TIMER: dispatch_source_timer_flags_t
DISPATCH_SOURCE_TYPE_VNODE: dispatch_source_vnode_flags_t
DISPATCH_SOURCE_TYPE_WRITE: n/a
按照这个意思应该是对第二个参数的详细描述,具体到哪里填什么,挖个坑,同上一个坑一起说.
至于第四个参数是队列,意思是将这个监听放到哪一个队列里面.
dispatch_source_t t = dispatch_source_create(dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t queue);
dispatch_source_set_event_handler第一个参数天的是给哪一个source添加事件
block中填写事件
dispatch_source_set_event_handler(dispatch_source_t source, ^{
});
与上一个道理相同不过第二个参数传入的是函数
dispatch_source_set_event_handler_f(dispatch_source_t source, dispatch_function_t handler)
//取消给定的source
dispatch_source_cancel(dispatch_source_t source);
//测试给定的source 如果被取消就返回非0,如果没被取消返回0
long result = dispatch_source_testcancel(dispatch_source_t source);
//在取消的时候加了一个block
dispatch_source_set_cancel_handler(dispatch_source_t source, ^{
});
//附上一份60秒发送短信验证码的代码供参考
- (void)timer
{
__block int timeout=60; //倒计时时间
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_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
dispatch_source_set_event_handler(_timer, ^{
if(timeout<=0){ //倒计时结束,关闭
dispatch_source_cancel(_timer);
dispatch_async(dispatch_get_main_queue(), ^{
//设置界面的按钮显示 根据自己需求设置
[l_timeButton setTitle:@"重新发送验证码" forState:UIControlStateNormal];
l_timeButton.userInteractionEnabled = YES;
});
}else{
//控制在60s内
int seconds = timeout % 60;
//判断是否正好为60s
if (timeout == 60) {
seconds = 60;
}
NSString *strTime = [NSString stringWithFormat:@"%.2d", seconds];
dispatch_async(dispatch_get_main_queue(), ^{
//设置界面的按钮显示 根据自己需求设置
NSLog(@"____%@",strTime);
[l_timeButton setTitle:[NSString stringWithFormat:@"%@秒后重新发送",strTime] forState:UIControlStateNormal];
l_timeButton.userInteractionEnabled = NO;
});
timeout--;
}
});
dispatch_resume(_timer);
}