博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【iOS 开发】延迟执行方法小总结
阅读量:5786 次
发布时间:2019-06-18

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

当需要实现类似“轮询”这种操作的时候,我们可能会希望有一个“被放缓了的” for 循环 —— 即当某次操作执行后,稍等一下再去执行下一次操作。这时有几种方法可以供我们使用,来实现这种效果,下面对比总结一下。


perform(_ aSelector: Selector, with anArgument: Any?, afterDelay delay: TimeInterval)

extension NSObject {    open func perform(_ aSelector: Selector, with anArgument: Any?, afterDelay delay: TimeInterval, inModes modes: [RunLoopMode])    open func perform(_ aSelector: Selector, with anArgument: Any?, afterDelay delay: TimeInterval)    open class func cancelPreviousPerformRequests(withTarget aTarget: Any, selector aSelector: Selector, object anArgument: Any?)    open class func cancelPreviousPerformRequests(withTarget aTarget: Any)}extension RunLoop {    open func perform(_ aSelector: Selector, target: Any, argument arg: Any?, order: Int, modes: [RunLoopMode])    open func cancelPerform(_ aSelector: Selector, target: Any, argument arg: Any?)    open func cancelPerformSelectors(withTarget target: Any)}复制代码

这是系统提供的 API,其中最简单的第 2 个方法可以通过指定方法、参数、延迟时间来实现延迟调用。

优点:使用简单、自带根据 target 取消调用的机制 并且可以指定对象、方法来取消延迟调用 使得这个方法可以完成一些复杂的延迟调用机制

缺点:系统帮你自动完成了很多操作,使得它不像定时器(NSTimer)那样高度可控。


scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer

open class Timer : NSObject {    public /*not inherited*/ init(timeInterval ti: TimeInterval, invocation: NSInvocation, repeats yesOrNo: Bool)    open class func scheduledTimer(timeInterval ti: TimeInterval, invocation: NSInvocation, repeats yesOrNo: Bool) -> Timer    public /*not inherited*/ init(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool)    open class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer}复制代码

通过常见的定时器也可以实现延迟调用,把 repeats 参数置为 false,可以实现类似上面的 perform 的效果。

优点:定时器状态可控,可以重新赋值,可以查看是否 valid 等

缺点:对比上面的 perform 方法可以直接传参,这里想要传参的话只能曲线救国:

  1. 把参数放在 timer 的 userInfo 里面,再把 timer 本身当成参数传递(这里使得代码可读性稍稍变差,但是好在 userInfo 里面什么都能放,这使得我们可以同时传递多个参数了)
  2. 如果你的代码可以不兼容 iOS 10 以下的系统,新的 API 可以让你不通过 selector 而是通过 block (closure) 执行代码

asyncAfter(deadline: DispatchTime, qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, execute work: @escaping @convention(block) () -> Swift.Void)

DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 1, execute: {    print("1 second after")})复制代码

上面这段代码,可以在 1 秒之后,通过主线程执行 print。值得注意的是,设定时间的时候,有两种类型,一种是 DispatchTime,这个时间本质上是相对时间,它会在系统休眠的时候暂停,另外一种是 DispatchWallTime,这个时间正如其名,是“墙上的挂钟时间”,是绝对时间,比如你可能希望某一个任务准确地在x小时、x分钟、x秒之后执行,这段时间可能发生任何事情,这时推荐使用 DispatchWallTime.

神奇而伟大的 GCD 这里就不多做介绍了,有太多文章讲解它了

优点:执行的是闭包,可以随意传参
缺点:一旦开启,无法取消,只能提前在闭包里面添加严谨的逻辑判断了

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

你可能感兴趣的文章
ng2路由延时加载模块
查看>>
使用GitHub的十个最佳实践
查看>>
脱离“体验”和“安全”谈盈利的游戏运营 都是耍流氓
查看>>
慎用!BLEU评价NLP文本输出质量存在严重问题
查看>>
基于干净语言和好奇心的敏捷指导
查看>>
Node.js 2017企业用户调查结果发布
查看>>
“软”苹果水逆的一周:杂志服务崩溃,新机型遭泄露,芯片首架离职
查看>>
JAVA的优势就是劣势啊!
查看>>
ELK实战之logstash部署及基本语法
查看>>
帧中继环境下ospf的使用(点到点模式)
查看>>
BeanShell变量和方法的作用域
查看>>
LINUX下防恶意扫描软件PortSentry
查看>>
由数据库对sql的执行说JDBC的Statement和PreparedStatement
查看>>
springmvc+swagger2
查看>>
软件评测-信息安全-应用安全-资源控制-用户登录限制(上)
查看>>
我的友情链接
查看>>
Java Web Application 自架构 一 注解化配置
查看>>
如何 debug Proxy.pac文件
查看>>
Python 学习笔记 - 面向对象(特殊成员)
查看>>
Kubernetes 1.11 手动安装并启用ipvs
查看>>