在Swift 2中,我能够使用nil
来延迟使用大型中央调度的操作:
dispatch_after
但是从Swift 3开始,这似乎不再编译。在现代Swift中编写它的首选方法是什么?
答案 0 :(得分:1035)
语法很简单:
xml
注意,将// to run something in 0.1 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// your code here
}
添加为seconds
的上述语法似乎是混淆的原因(特别是因为我们习惯于添加nsec)。 “将{秒添加为Double
”语法有效,因为Double
是deadline
,并且在幕后,有一个DispatchTime
运算符将采用+
并将这几秒钟添加到Double
:
DispatchTime
但是,如果您确实要向public func +(time: DispatchTime, seconds: Double) -> DispatchTime
添加整数msec,μs或nsec,您还可以向DispatchTime
添加DispatchTimeInterval
。这意味着你可以这样做:
DispatchTime
由于DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
os_log("500 msec seconds later")
}
DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(1_000_000)) {
os_log("1m μs seconds later")
}
DispatchQueue.main.asyncAfter(deadline: .now() + .nanoseconds(1_500_000_000)) {
os_log("1.5b nsec seconds later")
}
类中+
运算符的这种单独重载方法,所有这些都无缝地工作。
DispatchTime
有人询问如何取消已发送的任务。为此,请使用public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
。例如,这将启动一个将在五秒内触发的任务,或者如果视图控制器被解除并取消分配,则其DispatchWorkItem
将取消该任务:
deinit
请注意class ViewController: UIViewController {
private var item: DispatchWorkItem?
override func viewDidLoad() {
super.viewDidLoad()
item = DispatchWorkItem { [weak self] in
self?.doSomething()
self?.item = nil
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: item!)
}
deinit {
item?.cancel()
}
func doSomething() { ... }
}
中[weak self]
捕获列表的使用。这对于避免强大的参考周期至关重要。另请注意,这不会取消抢先取消,而只是暂停启动任务(如果尚未启动)。但是如果它在遇到DispatchWorkItem
调用时已经开始,则该块将完成执行(除非您手动检查块内的cancel()
)。
答案 1 :(得分:124)
Swift 4:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
// Code
}
对于.seconds(Int)
时间,也可以使用.microseconds(Int)
和.nanoseconds(Int)
。
答案 2 :(得分:57)
如果你只想要延迟功能
Swift 4& 5 强>
func delay(interval: TimeInterval, closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
closure()
}
}
您可以像以下一样使用它:
delay(interval: 1) {
print("Hi!")
}
答案 3 :(得分:16)
func delay(_ delay: Double, closure: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
答案 4 :(得分:5)
Swift 4
您可以在DispatchQueue上创建扩展并添加在内部使用DispatchQueue
asyncAfter函数的函数延迟
extension DispatchQueue {
static func delay(_ delay: DispatchTimeInterval, closure: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: closure)
}
}
并使用
DispatchQueue.delay(.milliseconds(10)) {
print("task to be done")
}
答案 5 :(得分:5)
接受的答案略有不同。
Swift 4
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + .milliseconds(500) +
.microseconds(500) + .nanoseconds(1000)) {
print("Delayed by 0.1 second + 500 milliseconds + 500 microseconds +
1000 nanoseconds)")
}
答案 6 :(得分:3)
致电DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)
我强烈建议使用Xcode工具转换为Swift 3(编辑>转换>转换为当前Swift语法)。它为我抓住了这个
答案 7 :(得分:2)
在Swift 4.1和Xcode 9.4.1中
简单的答案是...
//To call function after 5 seconds time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}
答案 8 :(得分:1)
以上提到的答案均未在非主线程上运行,因此加2美分。
在主队列(主线程)上
let mainQueue = DispatchQueue.main
let deadline = DispatchTime.now() + .seconds(10)
mainQueue.asyncAfter(deadline: deadline) {
// ...
}
OR
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) {
// ...
}
在全局队列上(非主线程,基于指定的QOS)。
let backgroundQueue = DispatchQueue.global()
let deadline = DispatchTime.now() + .milliseconds(100)
backgroundQueue.asyncAfter(deadline: deadline, qos: .background) {
// ...
}
OR
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + .milliseconds(100), qos: .background) {
// ...
}
答案 9 :(得分:1)
Swift 5及以上
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
// code to execute
})
答案 10 :(得分:0)
这在Swift 3中对我有用
let time1 = 8.23
let time2 = 3.42
// Delay 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
print("Sum of times: \(time1 + time2)")
}
答案 11 :(得分:0)
您可以使用
DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(100)) {
// Code
}
答案 12 :(得分:0)
试试这个
let when = DispatchTime.now() + 1.5
DispatchQueue.main.asyncAfter(deadline: when) {
//some code
}