cancel dispatch_after() method?
Solution 1
There is NO way to prevent a dispatch_block from executing once it has been dispatch to it's queue, meaning that your dispatch_after cannot be canceled. Only option is to add in your block a condition to be checked at runtime to prevent execution. ie.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), ^ {
if(self.shouldExecuteDispatchBlock)
{ // do your stuff } });
Solution 2
OK, so, with all answers collected, and possible solutions, seems like the best one for this case (preserving simplicity) is calling performSelector:withObject:afterDelay:
and cancelling it with cancelPreviousPerformRequestsWithTarget:
call when desired. In my case - just before scheduling next delayed call:
[NSObject cancelPreviousPerformRequestsWithTarget: self selector:@selector(myDelayedMethod) object: self];
[self performSelector:@selector(myDelayedMethod) withObject: self afterDelay: desiredDelay];
Solution 3
For this purpose i used this class:
https://github.com/SebastienThiebaud/dispatch_cancelable_block
you can call a cancel() function to revoke the execution of what's in the block.
Solution 4
Use a dispatch timer source (that is what dispatch_after
uses internally anyway).
A dispatch timer source can be canceled or its timer parameters changed after creation.
Comments
-
Oleg Shanyuk over 4 years
Is there a way to cancel dispatch_after() scheduled for some time in future, and haven't fired so far? I'm trying to make something like a scheduler for updates from server, and this method is just like I want, but, I'd love to cancel and re-schedule it at some point. Is it possible at all or I have to fallback and use NSTimer?
-
katleta3000 about 9 yearsIf you would use it in Swift - you can look it here github.com/katleta3000/CancelBlocks
-
Jonny almost 9 yearsHmmm so until the next time for execution of this block comes up (and it's set to be cancelled), I guess it would hog all the memory/objects until then. Maybe a problem if your cycles are like 60 minutes? :-)
-
Florian Burel almost 9 yearsYes and no. The block copy the memory, wich mean if you refere to a int value in your block, this one will be copied and will stay in memory as a duplicate for as long as the block live. But for object, it does not duplicate them, it copy the adress. MEaning if you refere an image, you will have one UIImage object in the heap but the block will only retain a pointer value (8 bytes in arch64) so, no biggie. Of course the image will be retain in memory untill the block goes out, so it won't be clean by arc.
-
Olie over 8 yearsI started down this path, but how does one do it with class methods (which is why I switched to
dispatch_after
)? -
Oleg Shanyuk over 8 years@Olie good one. Then you have to wrap those calls into instance, or use dispatch + flag (guess, second would be simpler)
-
Nick over 7 yearsI have turned this into a extension for DispatchQueue: github.com/nrbrook/DispatchAfterCancellable
-
user963601 about 7 yearsApple introduced
dispatch_block_cancel
in iOS 8. It asynchronously cancels blocks created withdispatch_block_create
. developer.apple.com/reference/dispatch/… -
MarcWan almost 6 yearsDoes this not require a run loop, however?
-
Oleg Shanyuk almost 6 years@MarcWan it is require a run loop - as any call to the
performSelector:afterDelay:
selectors -
nmr almost 4 yearsWorks well for e.g. watchdog timers.