문제

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.

도움이 되었습니까?

해결책

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top