我翻遍了苹果的iBook,找不到任何关于它的定义:
有人能解释一下dispatch_after的结构吗?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
我翻遍了苹果的iBook,找不到任何关于它的定义:
有人能解释一下dispatch_after的结构吗?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
当前回答
Swift 3.0 & Swift 4.0 & Swift 5.0中最简单的解决方案
func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
completion()
}
}
使用
delayWithSeconds(1) {
//Do something
}
其他回答
斯威夫特 3+
这在Swift 3+中是超级简单和优雅的:
DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) {
// ...
}
年长的回答:
为了扩展Cezary的答案,它将在1纳秒后执行,我必须执行以下操作以在4秒半后执行。
let delay = 4.5 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), block)
编辑:我发现我原来的代码有一点错误。如果不将NSEC_PER_SEC转换为Double类型,隐式类型将导致编译错误。
如果有人能提出一个更优的解决方案,我很乐意听听。
更清晰的结构概念:
dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?)
dispatch_time_t为UInt64。dispatch_queue_t实际上是一个NSObject的类型别名,但是你应该使用你熟悉的GCD方法来获取队列。该区块是一个快速关闭。具体来说,dispatch_block_t定义为()-> Void,相当于()->()。
使用示例:
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
print("test")
}
编辑:
我推荐使用@matt的延时函数。
编辑2:
在Swift 3中,GCD将会有新的包装器。请看这里:https://github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md
原来的例子在Swift 3中是这样写的:
let deadlineTime = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
print("test")
}
注意,你可以将deadlineTime声明写为DispatchTime.now() + 1.0,并得到相同的结果,因为+操作符被重写如下(与-类似):
func +(time: DispatchTime, seconds: Double) -> DispatchTime . func +(time: DispatchTime, seconds: Double func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime . func +(time: DispatchWalltime, interval: DispatchTimeInterval
这意味着如果您不使用DispatchTimeInterval enum,而只是写一个数字,则假定您使用的是秒。
对于多个函数使用这个。这对于静态函数或任何UI更新使用动画或活动加载器非常有帮助。
DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
// Call your function 1
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// Call your function 2
}
}
例如-在tableView重新加载之前使用动画。或任何其他UI更新后的动画。
*// Start your amination*
self.startAnimation()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
*// The animation will execute depending on the delay time*
self.stopAnimation()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
*// Now update your view*
self.fetchData()
self.updateUI()
}
}
保留当前队列!
除了很好地回答这个问题之外,您还可以考虑保留当前队列以防止不必要的主队列操作(例如,当您试图延迟一些异步操作时)。
func after(_ delay: TimeInterval,
perform block: @escaping ()->(),
on queue: DispatchQueue = OperationQueue.current?.underlyingQueue ?? .main) { // So this `queue` preserves the current queue and defaulted to the `main`. Also the caller can pass in the desired queue explicitly
queue.asyncAfter(deadline: .now() + delay, execute: block)
}
用法:
after(3) {
// will be executed on the caller's queue
print(Date())
}
我总是喜欢使用扩展而不是自由函数。
斯威夫特4
public extension DispatchQueue {
private class func delay(delay: TimeInterval, closure: @escaping () -> Void) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
class func performAction(after seconds: TimeInterval, callBack: @escaping (() -> Void) ) {
DispatchQueue.delay(delay: seconds) {
callBack()
}
}
}
按以下方法使用。
DispatchQueue.performAction(after: 0.3) {
// Code Here
}