I\'ve gone through the iBook from Apple, and couldn\'t find any definition of it:
Can someone explain the structure of dispatch_after
?
d
Another way is to extend Double like this:
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.
In Swift 3.0
Dispatch queues
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")
})
}
Dispatch after 5 seconds
DispatchQueue.main.after(when: DispatchTime.now() + 5) {
print("Dispatch after 5 sec")
}
matt's syntax is very nice and if you need to invalidate the block, you may want to use this :
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)
}
credits
Link above seems to be down. Original Objc code from Github
Although not the original question by the OP, certain NSTimer
related questions have been marked as duplicates of this question, so it is worth including an NSTimer
answer here.
NSTimer
vs dispatch_after
NSTimer
is more high level while dispatch_after
is more low level.NSTimer
is easier to cancel. Canceling dispatch_after
requires writing more code.NSTimer
Create an NSTimer
instance.
var timer = NSTimer()
Start the timer with the delay that you need.
// invalidate the timer if there is any chance that it could have been called before
timer.invalidate()
// delay of 2 seconds
timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
Add a function to be called after the delay (using whatever name you used for the selector
parameter above).
func delayedAction() {
print("Delayed action has now started."
}
timer.invalidate()
.repeats: true
. If you have a one time event with no need to cancel then there is no need to create the timer
instance variable. The following will suffice:
NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
See my fuller answer here.
Simplest solution in Swift 3.0 & Swift 4.0 & Swift 5.0
func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
completion()
}
}
Usage
delayWithSeconds(1) {
//Do something
}
Now more than syntactic sugar for asynchronous dispatches in Grand Central Dispatch (GCD) in Swift.
add Podfile
pod 'AsyncSwift'
Then,you can use it like this.
let seconds = 3.0
Async.main(after: seconds) {
print("Is called after 3 seconds")
}.background(after: 6.0) {
print("At least 3.0 seconds after previous block, and 6.0 after Async code is called")
}