88

我经常想在未来几微秒内执行一些代码。现在,我这样解决它:

- (void)someMethod
{
    // some code
}

还有这个:

[self performSelector:@selector(someMethod) withObject:nil afterDelay:0.1];

它有效,但我每次都必须创建一个新方法。是否可以使用块代替这个?基本上我正在寻找一种方法,如:

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

那对我真的很有用。

4

6 回答 6

107

没有内置的方法可以做到这一点,但通过类别添加也不错:

@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

感谢Mike Ash的基本实现。

于 2010-10-24T03:38:22.630 回答
41

这是我正在使用的基于 GCD 的简单技术:

void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
      dispatch_get_current_queue(), block);
}

我不是 GCD 专家,我对此解决方案的评论很感兴趣。

于 2011-01-20T16:01:24.887 回答
23

另一种方法(由于许多原因可能是最糟糕的方法)是:

[UIView animateWithDuration:0.0 delay:5.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
} completion:^(BOOL finished) {
    //do stuff here
}];
于 2011-11-26T23:19:27.830 回答
16

如果您特别需要更长的延迟,则上述解决方案可以正常工作。我使用@nick 的方法取得了巨大成功。

但是,如果您只是希望您的块在主循环的下一次迭代期间运行,您可以使用以下内容进一步修剪它:

[[NSOperationQueue mainQueue] addOperationWithBlock:aBlock];

这类似于使用 performSelector: with afterDelay of 0.0f

于 2011-07-23T20:54:10.997 回答
11

我使用了类似的代码:

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...  
    });
于 2013-09-11T12:19:26.900 回答
1

这里有一个很好的、完整的类别可以处理这种情况:

https://gist.github.com/955123

于 2012-08-23T19:25:57.943 回答