平常的开发中,经常要用到延时处理功能,一般比较实用的有2种方法,一是performSelector:withObject:afterDelay:
,还有一种是GCD的dispatch_after
函数,我觉得后者比前者用起来方便很多,因为是block,代码可以写在一个地方。但是dispatch_after
有个缺点,就是不能取消。我们做超时处理等功能时,需要在某些条件成功以后取消这个超时的处理。而performSelector
有cancelPreviousPerformRequestsWithTarget
来实现取消功能。好消息是在iOS8以后多了一个GCD的取消函数。代码如下:
dispatch_block_t block = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
NSLog(@"我被取消了,所以你看不到我");
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(),block );
dispatch_block_cancel(block);
// 因为有dispatch_block_cancel,所以你看不到打印。如果注释掉dispatch_block_cancel,就有打印
这里要特别说明一下,dispatch_block_t
其实就是typedef void (^dispatch_block_t)(void);
,它是一个普通的返回值为void,无参的block。dispatch_after
的函数声明:dispatch_after(dispatch_time_t when,dispatch_queue_t queue,dispatch_block_t block);
,如果要实现支持取消的dispatch_after
,第三个参数你就不能传普通的dispatch_block_t
,必须要传dispatch_block_create
或dispatch_block_create_with_qos_class
创建的block,否则不但不能取消,而且还会崩溃的。
dispatch_block_t block = ^{
NSLog(@"不能这样写,会崩溃的哦");
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(),block );
dispatch_block_cancel(block);