博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用GCD实现Delay Call的取消操作
阅读量:6454 次
发布时间:2019-06-23

本文共 3514 字,大约阅读时间需要 11 分钟。

取消任务在OC当中是NSOperation的专利,现在Swift的GCD也支持取消正在等待执行的Block操作了,代码如下所示:

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3, DispatchWorkItem{print("I'm here!")})//执行下面一行,则可取消3秒后的延迟操作item.cancel()复制代码

我们可以通过将一个Block封装到DispatchWorkItem对象中,然后对其发送cancle,来取消一个正在等待执行的block。

在这里我们自己封装实现一个GCD的delay call:

原版:

import Foundationtypealias Task = (_ cancle : Bool) -> Voidfunc delay(_ time: TimeInterval, task: @escaping() -> ()) -> Task? {    func dispatch_later(block: @escaping()->()) {        let t = DispatchTime.now() + time        DispatchQueue.main.asyncAfter(deadline: t, execute: block)    }    var closure : (() -> Void)? = task    var result : Task?    let delayedClosure : Task = {        cancle in        if let internalClosure = closure {            if cancle == false {                DispatchQueue.main.async(execute: internalClosure)            }        }        closure = nil        result = nil    }    result = delayedClosure    dispatch_later {        if let delayedClosure = result {            delayedClosure(false)        }    }    return result}func cancle(_ task: Task?) {    task?(true)}复制代码

最后的使用代码如下:

let task = delay(3){print("I will be cancle")}cancle(task)复制代码

要是一下就看明白了,就不用看下面的分析了。

自己写

先定义用来取消的block:

typealias Task = (_ cancle : Bool) -> Voidfunc cancle(_ task: Task?) {    task?(true)}复制代码

核心就是把task封装到delayedClosure这个闭包中,delayedClosure执行时会检查result是否为空,不为空就继续执行并且cancle为false就执行task,把result置空,后面当时间到了要调用delayedClosure的时候因为result为空了,所以就不会执行task了:

func delay(_ time: TimeInterval, task: @escaping()->()) -> Task? {    var result : Task?    let delayedClosure: Task = {cancle in        if result != nil {            if cancle == false {                DispatchQueue.main.async {                    task()                }            }            result = nil        }    }    result = delayedClosure    return result}复制代码

在delay中定义延迟执行的子方法dispatch_later,将delayedClosure封装成dispatch_later能调用的闭包:

func delay(_ time: TimeInterval, task: @escaping()->()) -> Task? {    var result : Task?    func dispatch_later(block: @escaping()->()) {        let t = DispatchTime.now() + time        DispatchQueue.main.asyncAfter(deadline: t, execute: block)    }    let delayedClosure: Task = {cancle in        if result != nil {            if cancle == false {                DispatchQueue.main.async {                    task()                }            }            result = nil        }    }    result = delayedClosure    dispatch_later {        delayedClosure(false)    }    return result}复制代码

到此为止就已经能实现延迟执行并取消task了。

原版的下面这句:

var closure : (() -> Void)? = task复制代码

将task赋值给可变变量closure,然后在delayedClosure中捕获closure,与result一起置为空,则可以在delayedClosure执行完后立即释放这个task。

如果不这样做的话,随着返回的Task被销毁,它所捕获的变量也会销毁。因此这只是一个优化。
然后在将if result != nil的判断写在dispatch_later调用的闭包中,代码就和原版一样了。

OC版本的:

Task delay(NSTimeInterval time, Blk task) {    __block Task result;    __block Blk closure = task;    Task delayClosure = ^(BOOL cancle) {        if (closure) {            Blk internalClosure = closure;            if (!cancle) {                dispatch_async(dispatch_get_main_queue(), ^{                    internalClosure();                });            }            closure = nil;        }        result = nil;    };    result = delayClosure;    dispatch_delay(time, ^{        if (result) {            result(false);        }    });    return result;}void dispatch_delay(NSTimeInterval time, Blk block) {    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), block);}复制代码

转载地址:http://nxfzo.baihongyu.com/

你可能感兴趣的文章
Linux系统编程——进程调度浅析
查看>>
大数据Lambda架构
查看>>
openCV_java 图像二值化
查看>>
状态模式
查看>>
删除CentOS / RHEL的库和配置文件(Repositories and configuraiton files)
查看>>
DJANGO变动库的一次真实手动经历
查看>>
8个基本的引导工具的网页设计师
查看>>
【下载分】C语言for循环语句PK自我活动
查看>>
VC++获得微秒级时间的方法与技巧探讨(转)
查看>>
HDOJ-1010 Tempter of the Bone
查看>>
MySQL my.cnf参数配置优化详解
查看>>
HDU/HDOJ 2102 A计划 广度优先搜索BFS
查看>>
JavaNIO基础02-缓存区基础
查看>>
阿里 Blink 正式开源,重要优化点解读
查看>>
日本开设无人机专业,打造无人机“人才市场”
查看>>
Exchange 2013 EAC之管理员重置普通用户密码
查看>>
三线跑酷例子BlocksRun的技术点
查看>>
如何应对DDOS网络攻击
查看>>
新闻奖颁给了一个写稿机器人(来自新华社)
查看>>
Android应用程序在新的进程中启动新的Activity的方法和过程分析
查看>>