2013-03-11 65 views
57

我需要在(相同)函数中执行两行之间添加延迟。是否有任何有利的选择来做到这一点?在执行下面两行之间添加延迟

注意:我不需要两个不同的函数来做到这一点,并且延迟不得影响其他函数的执行。

如:

line 1: [executing first operation]; 

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

line 3: [executing second operation]; 

任何帮助是明显的。在此先感谢...

回答

149

您可以使用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"); 
}); 

你还是应该问自己“我真的需要添加一个延迟”,因为它往往可以复杂代码,并导致竞争条件

+2

向人们警告这是正确的,但是如果您编码的控制器需要等待外部设备进行固定的处理时间,则它不是无意义的。 – user2161301 2015-10-02 11:55:41

+2

如何在写入搜索栏时延迟HTTP请求?在输入时过滤结果?在请求一个过滤列表之前等待一秒钟,而不是向服务器查询用户点击的每个按键,这听起来对我来说并不是什么废话。 – 2016-07-15 17:00:50

17

这条线在3秒后调用选择secondMethod:

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

与你期望的延迟使用它在你的第二个操作。如果您有很多代码,请将其置于其自己的方法中,并使用performSelector:调用该方法。它不会阻止像sleep

编辑UI:如果你不想让你可以添加一个类别中的第二种方法可以使用块与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); 
} 
+6

的OP明确指出他们不希望第二个方法:S – 2013-03-11 10:10:47

+0

他可以添加一个类别,能够使用块用'performSelector':http://stackoverflow.com/questions/4007023/blocks-instead - 执行selectorwithobjectafterlaylay – Sunkas 2013-03-11 10:31:22

+0

@Sunkas:谢谢你的答案。但我已经提到过我不想添加第二个函数。 – 2013-03-11 12:09:38

2

如果你的目标的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]; 
}); 
+1

你的意思是iOS 4? [Grand central dispatch Function Reference](http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2-SW3) – 2013-03-11 10:47:31

23

可以使用NSThread方法:

[NSThread sleepForTimeInterval: delay]; 

但是,如果你这样做,你会阻止应用程序的主线程上,所以只能这样做在后台线程。


或斯威夫特

NSThread.sleepForTimeInterval(delay) 

斯威夫特卡伦特3

Thread.sleep(forTimeInterval: delay) 
+0

我相信这应该是根据问题要求接受的答案。 – ACLima 2016-04-05 23:06:52

+1

@ACLima:对不起,'sleepForTimeInterval'会将线程休眠一段给定的时间间隔,这可能会影响其他同时执行的函数。 – 2016-04-15 07:18:19

+0

@KrishnaRajSalim我明白了,谢谢 – ACLima 2016-04-15 10:01:54

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的电话都是不同的(我需要这个添加到一个,太。)

0

Like @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:方法来代替。如果 不确定当前线程是否为主线程,则可以使用performSelectorOnMainThread:withObject:waitUntilDone:或 执行selectSelectorOnMainThread:withObject:waitUntilDone:modes:方法到 保证您的选择器在主线程上执行。要取消排队的消息,请使用cancelPreviousPerformRequestsWithTarget:或者 cancelPreviousPerformRequestsWithTarget:selector:object:method。