我从Apple那里浏览了iBook,找不到任何定义:
有人可以解释结构dispatch_after
吗?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
matt.. 1086
我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) }
现在你可以这样说:
delay(0.4) { // do stuff }
哇,一种你可以改善语言的语言.还有什么比这更好的?
似乎几乎不值得打扰,现在他们已经改进了调用语法:
func delay(_ delay:Double, closure:@escaping ()->()) { let when = DispatchTime.now() + delay DispatchQueue.main.asyncAfter(deadline: when, execute: closure) }
不要质疑你答案的正确性 - 但不是*"我经常使用dispatch_after"*代码气味最好是**而不是**提供便利功能? (8认同)
"一种可以改善语言的语言".我不明白定义一个全局函数如何改进语言,或者为什么这在C语言中是不可行的.也许如果你重载一个运算符;)`1.0 ~~ {code ...}` (7认同)
@ agf119105如果闭包中只有一行代码,则添加另一行代码(例如`return`). (4认同)
我只需要延迟计算的快捷方式,最后得到:`func delayInSec(delay:Double) - > dispatch_time_t {return dispatch_time(DISPATCH_TIME_NOW,Int64(delay*Double(NSEC_PER_SEC)))}` (2认同)
@GastonM不相关.传递函数_of本身_没有内存管理问题. (2认同)
Cezary Wojci.. 730
更清楚的结构:
dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?)
dispatch_time_t
是一个UInt64
.在dispatch_queue_t
被实际键入别名的NSObject
,但你应该只使用自己熟悉的GCD方法来获取队列.该块是一个Swift闭包.具体而言,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的非常好的delay
功能.
编辑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: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
这意味着如果您不使用DispatchTimeInterval
enum
并只写一个数字,则假定您使用秒.
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) } }
使用方法如下
let retVal = delay(2.0) { println("Later") } delay(1.0) { cancel_delay(retVal) }
学分
上面的链接似乎有所下降.来自Github的原始Objc代码
我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) }
现在你可以这样说:
delay(0.4) { // do stuff }
哇,一种你可以改善语言的语言.还有什么比这更好的?
似乎几乎不值得打扰,现在他们已经改进了调用语法:
func delay(_ delay:Double, closure:@escaping ()->()) { let when = DispatchTime.now() + delay DispatchQueue.main.asyncAfter(deadline: when, execute: closure) }
Swift 3.0和Swift 4.0中最简单的解决方案
func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) { DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { completion() } }
用法
delayWithSeconds(1) { //Do something }
Apple有一个针对Objective-C的dispatch_after片段:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ <#code to be executed after a specified delay#> });
这是移植到Swift 3 的相同片段:
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + <#delayInSeconds#>) { <#code to be executed after a specified delay#> }
为了扩展Cezary的答案,它将在1纳秒后执行,我必须在4秒半后执行以下操作.
DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) { // ... }
编辑:我发现我的原始代码有些错误.如果不将NSEC_PER_SEC转换为Double,则隐式类型会导致编译错误.
如果有人能提出更优化的解决方案,我会热衷于听到它.
== Swift 3的更新==
这在Swift 3中非常简单和优雅:
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)
更清楚的结构:
dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?)
dispatch_time_t
是一个UInt64
.在dispatch_queue_t
被实际键入别名的NSObject
,但你应该只使用自己熟悉的GCD方法来获取队列.该块是一个Swift闭包.具体而言,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的非常好的delay
功能.
编辑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: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
这意味着如果您不使用DispatchTimeInterval
enum
并只写一个数字,则假定您使用秒.
另一种方法是像这样扩展Double:
extension Double { var dispatchTime: dispatch_time_t { get { return dispatch_time(DISPATCH_TIME_NOW,Int64(self * Double(NSEC_PER_SEC))) } } }
然后你可以像这样使用它:
dispatch_after(Double(2.0).dispatchTime, dispatch_get_main_queue(), { () -> Void in self.dismissViewControllerAnimated(true, completion: nil) })
我喜欢亚光的延迟功能,但仅仅是出于偏好,我宁愿限制传递闭合.
在Swift 3.0中
派遣队列
DispatchQueue(label: "test").async { //long running Background Task for obj in 0...1000 { print("async \(obj)") } // UI update in main queue DispatchQueue.main.async(execute: { print("UI update on main queue") }) } DispatchQueue(label: "m").sync { //long running Background Task for obj in 0...1000 { print("sync \(obj)") } // UI update in main queue DispatchQueue.main.sync(execute: { print("UI update on main queue") }) }
5秒后发货
DispatchQueue.main.after(when: DispatchTime.now() + 5) { print("Dispatch after 5 sec") }