在执行以下两行之间添加延迟

时间:2013-03-11 09:59:00

标签: objective-c delay execution

我需要在(相同)函数中执行两行之间添加延迟。是否有任何有利的选择?

注意:我不需要两个不同的函数来执行此操作,延迟不得影响其他函数的执行。

例如:

line 1: [executing first operation];

line 2: Delay                        /* I need to introduce delay here */

line 3: [executing second operation];

任何帮助都是值得的。提前谢谢......

7 个答案:

答案 0 :(得分:184)

您可以使用gcd执行此操作,而无需创建其他方法

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
  NSLog(@"Do some work");
});

您仍然应该问自己“我真的需要添加延迟”,因为它通常会使代码复杂化并导致竞争条件

答案 1 :(得分:26)

您可以使用NSThread方法:

[NSThread sleepForTimeInterval: delay];

但是,如果您在主线程上执行此操作,则会阻止该应用,因此只能在后台线程上执行此操作。


或在Swift中

NSThread.sleepForTimeInterval(delay)
Swift 3中的

Thread.sleep(forTimeInterval: delay)

答案 2 :(得分:19)

此行在3秒后调用选择器secondMethod:

[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ];

在您的第二次操作中使用它并达到所需的延迟。如果您有很多代码,请将其放在自己的方法中,并使用performSelector:调用该方法。它不会像sleep

那样阻止用户界面

编辑:如果您不想要第二种方法,可以添加一个类别,以便能够使用带有performSelector的块:

@implementation NSObject (PerformBlockAfterDelay)

- (void)performBlock:(void (^)(void))block 
          afterDelay:(NSTimeInterval)delay
{
    block = [block copy];
    [self performSelector:@selector(fireBlockAfterDelay:) 
               withObject:block 
               afterDelay:delay];
}

- (void)fireBlockAfterDelay:(void (^)(void))block
{
    block();
}

@end

或者甚至更干净:

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

答案 3 :(得分:8)

我有几个回合制游戏,我需要AI在轮到之前暂停(以及轮到步骤之间)。我确信还有其他更有用的情况,延迟是最好的解决方案。在斯威夫特:

        let delay = 2.0 * Double(NSEC_PER_SEC) 
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) 
        dispatch_after(time, dispatch_get_main_queue()) { self.playerTapped(aiPlayView) }

我刚刚回到这里看看Objective-C调用是否不同。(我也需要将它添加到那个。)

答案 4 :(得分:4)

[检查2020年11月27日,并确认在Xcode 12.1上仍然正确]

当今最方便的方法:Xcode提供了一个代码段来执行此操作,您只需输入延迟值以及希望在延迟后运行的代码即可。

  1. 单击Xco​​de右上方的+按钮。
  2. 搜索after
  3. 它将仅返回1个搜索结果,这是所需的代码段(请参见屏幕截图)。双击它就可以了。

screenshot illustrating how to get the snippet from within Xcode itself

答案 5 :(得分:3)

如果您的目标是iOS 4.0+,则可以执行以下操作:

[executing first operation];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [executing second operation];
});

答案 6 :(得分:0)

就像@Sunkas写的那样,performSelector:withObject:afterDelay:dispatch_after的链接,只是它更短,而且你有正常的objective-c语法。如果你需要将参数传递给你想要延迟的块,你可以通过参数withObject传递它们,你将在你调用的selector中收到它:

[self performSelector:@selector(testStringMethod:) 
           withObject:@"Test Test" 
           afterDelay:0.5];

- (void)testStringMethod:(NSString *)string{
    NSLog(@"string  >>> %@", string);
}

如果您仍然想在主线程或当前线程上执行它,那么有一些特定的方法可以指定它。苹果文档告诉我们:

  

如果希望在运行循环处于某种模式时将消息出列   除默认模式外,请使用   performSelector:withObject:afterDelay:inModes:method。如果你   不确定当前线程是否是主线程,你可以   使用performSelectorOnMainThread:withObject:waitUntilDone:或   performSelectorOnMainThread:withObject:waitUntilDone:modes:方法到   保证您的选择器在主线程上执行。要取消   排队的消息,使用cancelPreviousPerformRequestsWithTarget:或   cancelPreviousPerformRequestsWithTarget:selector:object:method。