如何在Objective-C和Swift中进行等待

48

我想在2秒后更改我的UILabel的文本。

我尝试将我的UILabel的文本设置为“A text”,然后使用sleep(2),最后再将文本更改为“Another text”

但是sleep(2)只会冻结应用程序,并且“Another text”会在2秒钟内设置而不显示“A text”

如何使“A text”显示2秒钟,然后显示“Another text”


8个回答

89

我知道我来晚了。但我发现还没有人提到线程休眠。如果你正在使用GCD调用该函数,可以使用以下代码:

NSThread sleepForTimeInterval:2.0f];   

延迟线程2秒。

[self changeText: @"A text"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  //Here your non-main thread.
  [NSThread sleepForTimeInterval:2.0f];   
  dispatch_async(dispatch_get_main_queue(), ^{
    //Here you returns to main thread.
    [self changeText: @"Another text"];
  });
});

编辑2(2015年2月)

我认为NSTimer是一个很好的解决方案。我的解决方案只是提供了另一种实现NSTimer目标的选择。

请阅读:如何使用NSTimer?

[NSTimer scheduledTimerWithTimeInterval:2.0
         target:self
         selector:@selector(doSomethingWhenTimeIsUp:)
         userInfo:nil
         repeats:NO];

在这个类中,你需要使用这个方法:
- (void) doSomethingWhenTimeIsUp:(NSTimer*)t {
  // YES! Do something here!!
}

编辑 3(2016年5月)

在Swift 2.0中,您可以使用以下方法:

NSTimer.scheduledTimerWithTimeInterval(2.0, 
                                       target: self, 
                                       selector: "doSomethingWhenTimeIsUp:", 
                                       userInfo: nil, 
                                       repeats: false)

它创建了一个NSTimer实体,并自动将计时器添加到创建计时器的NSThread关联的NSRunLoop中。 编辑4(2016年6月) 在Swift 2.2中,调用select的方式为:
#selector(doSomethingWhenTimeIsUp(_:))

所以,它有点像:
NSTimer.scheduledTimerWithTimeInterval(2.0,
                                       target: self,
                                       selector: #selector(doSomethingWhenTimeIsUp()),
                                       userInfo: nil,
                                       repeats: false)

编辑5(2016年10月)

在Swift 3中,调用select的方法如下:

#selector(doSomethingWhenTimeIsUp)

所以,它有点像:

Timer.scheduledTimer(timeInterval: 2.0,
                     target: self,
                     selector: #selector(doSomethingWhenTimeIsUp),
                     userInfo: nil,
                     repeats: false)

然后,该函数应该如下所示:

@objc private func doSomethingWhenTimeIsUp(){
  // Do something when time is up
}

编辑6(2018年5月)Swift 4中,我们可以按照以下方式进行操作。

let delaySeconds = 2.0
DispatchQueue.main.asyncAfter(deadline: .now() + delaySeconds) {
  doSomethingWhenTimeIsUp()
}  

那么,函数应该看起来像这样:
private func doSomethingWhenTimeIsUp(){
  // Do something when time is up
}

这对我在dispatch_async中使用do-while循环非常有用。谢谢。+1 - So Over It
特别是对于那些与线程密切相关的人,这是一个更好的答案。++ - Matthew Anderson

44

您可以使用

[self performSelector:@selector(changeText:) withObject:text afterDelay:2.0];

或者如果您想定期显示它,请使用NSTimer类。


30

Grand Central Dispatch有一个辅助函数dispatch_after(),可用于在延迟后执行操作。您可以指定等待执行的时间和要运行的dispatch_queue_t实例。您可以使用dispatch_get_main_queue()在主线程上执行。

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){
    // do something
});

Swift 3中,以上示例可以编写为:

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    // do something
}

12

你可以使用NSTimer,如下所示 -

[NSTimer scheduledTimerWithTimeInterval:0.5 
                                 target:self 
                               selector:@selector(updateLabel:) 
                               userInfo:nil 
                                repeats:YES];

定义另一个名为updateLabel的方法,并在其中进行更新。根据需要定义你的timeInterval...

同时将repeats设置为YES可以确保该选择器每0.5秒执行一次(在上述情况下)。


5
您可以使用计时器来完成此操作,例如。
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(eventToFire:) userInfo:nil repeats:YES]; // Fire every 4 seconds.
   
...

- (void)eventToFire:(NSTimer*)timer {
  // Do Something
}

2
这是因为视图直到运行循环的结尾才会更新。不要使用睡眠,而应该使用NSTimer来设置特定的时间来更新视图。

2
你需要使用计时器。使用睡眠会暂停整个程序。请参考NSTimer

0

以下方法很好。

你可以将

sleep(1);

替换为

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接