在Swift 2中,我可以使用dispatch_after
来延迟使用grand central dispatch的操作:
var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
// your function here
})
但这似乎不再编译自斯威夫特3。什么是首选的方式来写这在现代斯威夫特?
9条答案
按热度按时间piwo6bdm1#
其语法简单明了:
请注意,上述将
seconds
添加为Double
的语法似乎会引起混淆(特别是因为我们习惯于添加nsec)。“将秒添加为Double
“语法之所以有效,是因为deadline
是一个DispatchTime
,并且在幕后,有一个+
运算符,它将取一个Double
,并在DispatchTime
上加上那么多秒:但是,如果你真的想给
DispatchTime
加上整数毫秒、微秒或纳秒,你也可以给DispatchTime
加上一个DispatchTimeInterval
。由于
DispatchTime
类中+
运算符的这个单独的重载方法,所有这些都可以无缝地工作。有人问如何取消一个已分派的任务。要做到这一点,请使用
DispatchWorkItem
。例如,这将启动一个将在五秒后触发的任务,或者如果视图控制器被解除并重新分配,则其deinit
将取消该任务:请注意
DispatchWorkItem
中[weak self]
捕获列表的使用。这对于避免强引用循环至关重要。还要注意,这不会执行抢先取消,而只是在任务尚未启动时停止任务启动。但如果任务在遇到cancel()
调用时已经启动,块将完成其执行(除非您手动检查块内的isCancelled
)。快速并发
虽然最初的问题是关于旧的GCD
dispatch_after
与新的asyncAfter
API,但这引发了如何在新的Swift并发及其async
-await
中实现相同行为的问题。从iOS 16和macOS 13开始,我们倾向于Task.sleep(for:)
:或者
或者,如果我们需要重新支持iOS 13和macOS 10.15,我们将使用
Task.sleep(nanoseconds:)
。要支持取消,请保存
Task
:或者在SwiftUI中,我们可以使用
.task {…}
视图修饰符,它“将在视图消失后的某个时间点自动取消任务,直到动作完成。”我们甚至不需要保存Task
以便以后手动取消。我们应该认识到,在Swift并发之前,调用任何
sleep
函数都是一个反模式,我们会刻意避免,因为它会阻塞当前线程。但即使在后台线程中使用也会有问题,因为GCD工作线程池非常有限。阻塞当前线程,因此可以安全地从任何参与者(包括主要参与者)使用。amrnrhlw2#
对于时间
.seconds(Int)
,也可以使用.microseconds(Int)
和.nanoseconds(Int)
。tpxzln5u3#
如果你只想要延迟函数
雨燕4和5
您可以像这样使用它:
llmtgqce4#
Swift 3发布后,还必须添加@escaping
ioekq8ef5#
一个有点不同的味道的接受答案。
1tu0hz3e6#
您可以在DispatchQueue上创建一个扩展并添加函数delay,该函数在内部使用
DispatchQueue
asyncAfter函数并使用
vyswwuz27#
调用
DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)
我强烈推荐使用Xcode工具转换到Swift3(编辑〉转换〉到当前SwiftSyntax)。
lxkprmvk8#
Swift 5及以上
aemubtdh9#
没有一个答案提到运行在非主线程上,所以加上我的两分钱。
在主队列上(主线程)
或
在全局队列上(非主线程,基于指定的QOS)。
或