如何将方法调用延迟1秒钟?


164

有一种简单的方法可以将方法调用延迟1秒吗?

UIImageView对触摸事件有反应。当检测到触摸时,应用中会发生一些动画。一秒钟后,我想调用另一个方法。在这种情况下,我不能使用animationDidStop选择器。


当然,有几种方法可以做到这一点,其中一种可能就是简单地使用sleep()将程序/线程挂起数毫秒,但是我想您可能想告诉我们您到底要完成什么?这样做吗?我的意思是,您的实际问题是什么?延迟方法调用的想法似乎是一种“解决方案”,听起来似乎不太好。因此,只需告诉我们更多有关您构想的方案。

Answers:


254
performSelector:withObject:afterDelay:

文件参考



有什么方法可以调用方法的返回值?或者,如果我想从中获取一些信息,是否需要对其进行设置以修改参数?
Gordon Gustafson

如果有人对如何取消计划的调用感兴趣:[NSObject cancelPreviousPerformRequestsWithTarget:yourTarget选择器:aSelector对象:anArgument];
vir我们

192

您也可以使用一个块

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [object method]; 
});

大多数时候,您将要使用dispatch_get_main_queue,尽管如果该方法中没有UI,则可以使用global queue

编辑:

Swift 3版本:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    object.method()
}

同样,这DispatchQueue.global().asyncAfter(...可能也是一个不错的选择。


发现将C和ObjC直接混合时,此解决方案比performSelector容易
Paul Slocum

1
不幸的是,自iOS6起不赞成使用dispatch_get_current_queue
chrisben

3
已更新为使用dispatch_get_main_queue而不是dispatch_get_current_queue
mcfedr 2013年

2
Xcode现在将自动完成此操作,只需开始键入dispatch_after并按Enter
mcfedr 2014年

1
特别是现在Xcode在键入时会自动完成此操作dispatch_after,这确实是一种非常简单的方法,此外,您还可以将属性传递给所调用的方法,这很棒。
Erik van der Neut 2015年

128

最好的方法是:

[self performSelector:@selector(YourFunctionName) 
           withObject:(can be Self or Object from other Classes) 
           afterDelay:(Time Of Delay)];

您还可以将nil作为withObject参数传递。

例如:

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

3
你为什么要把自我传递给自我?
埃里克

2
为什么将变量传递给带有零参数的方法?
hellozimi 2014年

23

已经有很多答案,而且都是正确的。如果您要使用,则dispatch_after应该Code Snippet Library在右下方的内找到片段(可以在其中选择UI元素)。

在此处输入图片说明

因此,您只需要通过在代码中编写dispatch来调用此代码段:

在此处输入图片说明



9

你也可以:

[UIView animateWithDuration:1.0
                 animations:^{ self.view.alpha = 1.1; /* Some fake chages */ }
                 completion:^(BOOL finished)
{
    NSLog(@"A second lapsed.");
}];

在这种情况下,您必须伪造对某些视图的某些更改才能获得动画效果。确实是骇人听闻的,但是我喜欢基于块的东西。或在下面总结@mcfedr答案。


waitFor(1.0, ^
{
    NSLog(@"A second lapsed");
});

typedef void (^WaitCompletionBlock)();
void waitFor(NSTimeInterval duration, WaitCompletionBlock completion)
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC),
                   dispatch_get_main_queue(), ^
    { completion(); });
}

不能确定,但​​是我认为您建议的第一个选项可能会有用户应注意的副作用,例如,阻止用户在部分UI上的交互。我的直觉是,这还会导致不必要的CPU或其他资源消耗,但是我没有检查。
比约恩·罗奇

8

你可以这样做

[self performSelector:@selector(MethodToExecute) withObject:nil afterDelay:1.0 ];

4

斯威夫特2.x

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
 dispatch_after(delayTime, dispatch_get_main_queue()) {
 print("do some work")
}

Swift 3.x-&-Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    print("do some work")
}

或通过 escaping closure

func delay(seconds: Double, completion: @escaping()-> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + seconds, execute: completion)
}

1

选中的解决方案中有一个Swift 3解决方案:

self.perform(#selector(self.targetMethod), with: self, afterDelay: 1.0)

而且有方法

@objc fileprivate func targetMethod(){

}


-34

注意:这将暂停您的整个线程,而不仅仅是一种方法。
在调用您的方法之前,先调用睡眠/等待/暂停1000 ms吗?

Sleep(1000); // does nothing the next 1000 mSek

Methodcall(params); // now do the real thing

编辑:上面的答案适用于一般问题“如何将方法调用延迟1秒钟?”,这是在回答时提出的问题(实际上答案是在原始问题的7分钟之内给出的:- ))。当时没有提供有关该语言的信息,因此请停止谈论使用XCode或缺少类的正确睡眠方式。


仅在当前线程中,其他线程才会继续运行。
马克夏邦诺

4
真是的 我知道为什么这被否决了几次,但是到底是谁在-27看到这个并决定还需要另一个?是-3还是不能理解这一点。为什么不编辑答案以说“这将使您的整个线程暂停”或其他内容,而不是给人们打分呢?
艾伯特·伦肖2015年

那么,如果您只想暂停整个线程怎么办?如果它带有一个体面的警告,似乎是一个有效的选择。
Departamento B

@AlbertRenshaw我完全同意你的看法。我在这里和它的35跌落,我给了他我的。我看到的更像是对知名度低的用户的攻击。没有人会做任何编辑或指定任何东西。今天我已经看到一个答案,那个人真的淹死了。这个人做的唯一错误是他/她用客观的c语言在一个迅速的问题下回答了。如果这是一个很大的错误,我想在客观c问题下给出这么多迅速的答案。
soorej babu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.