Objective-C delay action with blocks
IosObjective CCocoa TouchIos Problem Overview
I know that there are several ways of delaying an action in Objective-C like:
performSelector:withObject:afterDelay:
or using NSTimer
.
But there is such a fancy thing called blocks where you can do something like this:
[UIView animateWithDuration:1.50 delay:0 options:(UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionBeginFromCurrentState) animations:^{
}completion:^(BOOL finished){
}];
Unfortunately, this method applies only to animating things.
How can I create a delay with a block in one method so I don't have to use all those @selectors
and without the need to create a new separate method? Thanks!
Ios Solutions
Solution 1 - Ios
use dispatch_after:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
[self doSometingWithObject:obj1 andAnotherObject:obj2];
});
Solution 2 - Ios
Expanding on the accepted answer, I created a Helper function for anyone who doesn't care to memorize the syntax each time they want to do this :) I simply have a Utils class with this:
Usage:
[Utils delayCallback:^{
//--- code here
} forTotalSeconds:0.3];
Helper method:
+ (void) delayCallback: (void(^)(void))callback forTotalSeconds: (double)delayInSeconds{
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if(callback){
callback();
}
});
}
Solution 3 - Ios
Xcode 11.3.1 (at least, and also other versions of Xcode) provides a code snippet to do this where you just have to enter the delay value and the code you wish to run after the delay.
- click on the
+
button at the top right of Xcode. - search for
after
- It will return only 1 search result, which is the desired snippet (see screenshot). Double click it and you're good to go.
Solution 4 - Ios
Here is how you can trigger a block after a delay in Swift:
runThisAfterDelay(seconds: 4) { () -> () in
print("Prints this 4 seconds later in main queue")
// Or just call animatedMyObject() right here
}
/// EZSwiftExtensions
func runThisAfterDelay(seconds seconds: Double, after: () -> ()) {
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue(), after)
}
Its included as a standard function in my repo: https://github.com/goktugyil/EZSwiftExtensions