Blocks instead of performSelector:withObject:afterDelay: [duplicate]
I often want to execute some code a few microseconds in the future. Right now, I solve it like this:
- (void)someMethod
{
// some code
}
And this:
[self performSelector:@selector(someMethod) withObject:nil afterDelay:0.1];
It works, but I have to create a new method every time. Is it possible to use blocks instead of this? Basically I'm lo开发者_如何学运维oking for a method like:
[self performBlock:^{
// some code
} afterDelay:0.1];
That would be really useful to me.
There's no built-in way to do that, but it's not too bad to add via a category:
@implementation NSObject (PerformBlockAfterDelay)
- (void)performBlock:(void (^)(void))block
afterDelay:(NSTimeInterval)delay
{
block = [[block copy] autorelease];
[self performSelector:@selector(fireBlockAfterDelay:)
withObject:block
afterDelay:delay];
}
- (void)fireBlockAfterDelay:(void (^)(void))block {
block();
}
@end
Credit to Mike Ash for the basic implementation.
Here's a simple technique, based on GCD, that I'm using:
void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
dispatch_get_current_queue(), block);
}
I'm not a GCD expert, and I'd be interested in comments on this solution.
Another way (perhaps the worst way to do this for many reasons) is:
[UIView animateWithDuration:0.0 delay:5.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
} completion:^(BOOL finished) {
//do stuff here
}];
If you specifically need a longer delay, the solutions above work just fine. I've used @nick's approach with great success.
However, if you just want your block to run during the next iteration of the main loop, you can trim it down even further with just the following:
[[NSOperationQueue mainQueue] addOperationWithBlock:aBlock];
This is akin to using performSelector: with afterDelay of 0.0f
I used similar code like this:
double delayInSeconds = 0.2f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//whatever you wanted to do here...
});
There's a nice, complete category that handles this situation here:
https://gist.github.com/955123
精彩评论