块而不是performSelector:withObject:afterDelay:

时间:2010-10-24 03:20:37

标签: iphone objective-c cocoa-touch ios objective-c-blocks

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

- (void)someMethod
{
    // some code
}

而且:

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

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

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

这对我来说真的很有用。

6 个答案:

答案 0 :(得分:106)

没有内置的方法可以做到这一点,但通过类别添加并不是太糟糕:

@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的基本实施。

答案 1 :(得分: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专家,我对此解决方案的评论感兴趣。

答案 2 :(得分:22)

另一种方式(也许是出于多种原因最糟糕的做法)是:

[UIView animateWithDuration:0.0 delay:5.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
} completion:^(BOOL finished) {
    //do stuff here
}];

答案 3 :(得分:16)

如果你特别需要更长的延迟,上面的解决方案就可以了。我用@ nick的方法取得了巨大的成功。

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

[[NSOperationQueue mainQueue] addOperationWithBlock:aBlock];

这类似于使用performSelector:afterDelay为0.0f

答案 4 :(得分: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...  
    });

答案 5 :(得分:1)

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

https://gist.github.com/955123