views:

58

answers:

1

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 looking for a method like:

[self performBlock:^{
    // some code
} afterDelay:0.1];

That would be really useful to me.

+5  A: 

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.

John Calsbeek
note: you should always choose a prefix for your category methods, such as `mon_performBlock:afterDelay:`. this will reduce the possibility of your methods colliding with other implementations. the most common example: apple decides to add this method -- oops, your method will not replace what already loaded and if it did... it would be even more painful.
Justin
I should note that the idea of `[self performBlock:^{/* some block */} afterDelay:0.1]` doesn't make much sense. Why is this attached to an object at all? What role does `self` have in the firing of the block? You'd be better-off writing a C function `RunBlockAfterDelay(void (^block)(void), NSTimeInterval delay)`, though this does necessitate creating a temporary object whose sole job is to implement `-fireBlockAfterDelay:`.
Kevin Ballard
@Kevin: For convenience only. If you wanted to to it properly than using GDC directly and call the `dispatch_after(dispatch_time_t, dispatch_queue_t, dispatch_block_t)` function is the correct way to do it.
PeyloW
PeyloW is right, the cleanest way to do this would probably be to use Grand Central Dispatch.
John Calsbeek