本文翻译自:dispatch_after - GCD in Swift?
I've gone through the iBook from Apple, and couldn't find any definition of it: 我从Apple那里浏览了iBook ,找不到任何定义:
Can someone explain the structure of dispatch_after
? 有人可以解释dispatch_after
的结构吗?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
#1楼
参考:https://stackoom.com/question/1cqTw/dispatch-after-Swift中的GCD
#2楼
A clearer idea of the structure: 更清楚的结构:
dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?)
dispatch_time_t
is a UInt64
. dispatch_time_t
是一个UInt64
。 The dispatch_queue_t
is actually type aliased to an NSObject
, but you should just use your familiar GCD methods to get queues. dispatch_queue_t
实际上是NSObject
别名,但您应该使用熟悉的GCD方法来获取队列。 The block is a Swift closure. 该块是一个Swift闭包。 Specifically, dispatch_block_t
is defined as () -> Void
, which is equivalent to () -> ()
. 具体来说, dispatch_block_t
定义为() -> Void
,相当于() -> ()
。
Example usage: 用法示例:
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
print("test")
}
EDIT: 编辑:
I recommend using @matt's really nice delay
function . 我建议使用@ matt的非常好的delay
功能 。
EDIT 2: 编辑2:
In Swift 3, there will be new wrappers for GCD. 在Swift 3中,将有新的GCD包装器。 See here: https://github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md 请参阅: https : //github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md
The original example would be written as follows in Swift 3: 原始示例将在Swift 3中编写如下:
let deadlineTime = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
print("test")
}
Note that you can write the deadlineTime
declaration as DispatchTime.now() + 1.0
and get the same result because the +
operator is overridden as follows (similarly for -
): 请注意,您可以将deadlineTime
声明写为DispatchTime.now() + 1.0
并获得相同的结果,因为+
运算符被覆盖如下(类似于-
):
-
func +(time: DispatchTime, seconds: Double) -> DispatchTime
-
func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
This means that if you don't use the DispatchTimeInterval
enum
and just write a number, it is assumed that you are using seconds. 这意味着如果您不使用DispatchTimeInterval
enum
并只写一个数字,则假定您使用秒。
#3楼
Swift 3+ Swift 3+
This is super-easy and elegant in Swift 3+: 这在Swift 3+中非常简单和优雅:
DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) {
// ...
}
Older Answer: 旧答案:
To expand on Cezary's answer, which will execute after 1 nanosecond, I had to do the following to execute after 4 and a half seconds. 为了扩展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)
Edit: I discovered that my original code was slightly wrong. 编辑:我发现我的原始代码有点错误。 Implicit typing causes a compile error if you don't cast NSEC_PER_SEC to a Double. 如果不将NSEC_PER_SEC转换为Double,则隐式类型会导致编译错误。
If anyone can suggest a more optimal solution I'd be keen to hear it. 如果有人能提出更优化的解决方案,我会热衷于听到它。
#4楼
I use dispatch_after
so often that I wrote a top-level utility function to make the syntax simpler: 我经常使用dispatch_after
因此我编写了一个顶级实用程序函数来使语法更简单:
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
And now you can talk like this: 现在你可以这样说:
delay(0.4) {
// do stuff
}
Wow, a language where you can improve the language. 哇,一种你可以改善语言的语言。 What could be better? 还有什么比这更好的?
Update for Swift 3, Xcode 8 Seed 6 更新Swift 3,Xcode 8 Seed 6
Seems almost not worth bothering with, now that they've improved the calling syntax: 似乎几乎不值得打扰,现在他们已经改进了调用语法:
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
#5楼
matt's syntax is very nice and if you need to invalidate the block, you may want to use this : matt的语法非常好,如果你需要使块无效,你可能想要使用它:
typealias dispatch_cancelable_closure = (cancel : Bool) -> Void
func delay(time:NSTimeInterval, closure:()->Void) -> dispatch_cancelable_closure? {
func dispatch_later(clsr:()->Void) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(time * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), clsr)
}
var closure:dispatch_block_t? = closure
var cancelableClosure:dispatch_cancelable_closure?
let delayedClosure:dispatch_cancelable_closure = { cancel in
if closure != nil {
if (cancel == false) {
dispatch_async(dispatch_get_main_queue(), closure!);
}
}
closure = nil
cancelableClosure = nil
}
cancelableClosure = delayedClosure
dispatch_later {
if let delayedClosure = cancelableClosure {
delayedClosure(cancel: false)
}
}
return cancelableClosure;
}
func cancel_delay(closure:dispatch_cancelable_closure?) {
if closure != nil {
closure!(cancel: true)
}
}
Use as follow 使用方法如下
let retVal = delay(2.0) {
println("Later")
}
delay(1.0) {
cancel_delay(retVal)
}
Link above seems to be down. 上面的链接似乎有所下降。 Original Objc code from Github 来自Github的原始Objc代码
#6楼
Another way is to extend Double like this: 另一种方法是像这样扩展Double:
extension Double {
var dispatchTime: dispatch_time_t {
get {
return dispatch_time(DISPATCH_TIME_NOW,Int64(self * Double(NSEC_PER_SEC)))
}
}
}
Then you can use it like this: 然后你可以像这样使用它:
dispatch_after(Double(2.0).dispatchTime, dispatch_get_main_queue(), { () -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
})
I like matt's delay function but just out of preference I'd rather limit passing closures around. 我喜欢亚光的延迟功能,但仅仅是出于偏好,我宁愿限制传递闭合。