我需要在(相同)函数中执行两行之间添加延迟。是否有任何有利的选择?
注意:我不需要两个不同的函数来执行此操作,延迟不得影响其他函数的执行。
例如:
line 1: [executing first operation];
line 2: Delay /* I need to introduce delay here */
line 3: [executing second operation];
任何帮助都是值得的。提前谢谢......
答案 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提供了一个代码段来执行此操作,您只需输入延迟值以及希望在延迟后运行的代码即可。
+
按钮。after
答案 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。