在Cocoa中等待指定的时间长度

29

有没有比我下面的代码更直观的方式在Cocoa中等待一段特定时间的方法?

- (void) buttonPressed {
    [self makeSomeChanges];

    // give the user some visual feedback and wait a bit so he can see it
    [self displayThoseChangesToTheUser];
    [self performSelector:@selector(buttonPressedPart2:) withObject:nil afterDelay:0.35];
}

- (void) buttonPressedPart2: (id)unused {
    [self automaticallyReturnToPreviousView];
}

仅仅为了明确,这段代码没有 功能性 的问题--我唯一的不满意是 风格上 的问题。在我的情况下,程序流程足够简单,所以它可以工作,但是如果尝试将其封装或添加一些条件语句,情况可能会变得很糟糕。我一直在困扰这样一件事,就是我无法像下面这个虚构的例子那样等待一段时间,然后返回到代码中同样的点:

- (void) buttonPressed {
    [self doStuff];
    [UIMagicUnicorn waitForDuration:0.35];
    [self doStuffAfterWaiting];
}

相关链接:https://dev59.com/nHM_5IYBdhLWcg3wRw51 - Jon Schneider
7个回答

74

有一个

usleep(1000000);
并且
[NSThread sleepForTimeInterval:1.0f];

这两个将会睡眠1秒钟。


11
两者都会阻止线程执行其他操作。如果发生在主用户界面线程中,那就很糟糕。 - pestilence669
3
没问题。如果您需要在此期间使UI具有响应性,那么建议采用问题中建议的方法,即使用NSTimer定时器(如您所建议的)或在后台执行此延迟的线程。 - Brad Larson
谢谢 - 这就是我想知道的,如果“sleep”是我想要搜索的“wait”的几个同义词之一,我可能会偶然发现它。同时也感谢Pestilence提供的关于何时使用这些的警告。 - Purple Ninja Girl
使用带有块的RunAfterDelay方法的方法不会阻塞您的主线程。 - Andrew Rondeau

13

这是使用NSTimer的方式。它可能比你正在使用的方法更丑陋,但它允许重复事件,所以我更喜欢它。

[NSTimer scheduledTimerWithTimeInterval:0.5f 
                                 target:self
                               selector: @selector(doSomething:) 
                               userInfo:nil
                                repeats:NO];

你需要避免像usleep()这样的函数,它会让你的应用程序挂起并且感觉不响应。


8
如果你从主线程调用usleep(),它会使你的应用程序挂起并感觉不响应,所以要避免使用这种方式。 - chown

3
我不确定它是否存在(尚未),但是在10.6中使用块(或者在10.5和iPhone上使用PLBlocks)编写一个小包装器应该很容易,像performBlock:afterDelay:一样,可以完全满足您的需求,而无需使整个线程休眠。这将是一个非常有用的小代码片段。

Mike Ash在他的博客中写过类似这种方法的文章

NSString *something = ...;
RunAfterDelay(0, ^{
    NSLog(@"%@", something);
    [self doWorkWithSomething: something];
});

或者直接使用NSTimer的scheduledTimerWithTimeInterval:repeats:block:。 - uchuugaka
可能在10.6版本中不存在...我记不清了。 - uchuugaka

2
您可能想使用NSTimer,并将其作为回调发送“doStuffAfterWaiting”消息。任何类型的“sleep”都会阻塞线程,直到它醒来。如果它在您的UI线程中,则会导致应用程序出现“死机”。即使不是这种情况,也是不好的形式。回调方法将释放CPU以执行其他任务,直到达到指定的时间间隔。
文档提供了使用示例,并讨论了如何在何处创建计时器的差异。
当然,performSelector:afterDelay:也可以实现同样的功能。

2
一个简单的usleep有什么问题吗?我的意思是,除了要保持"Cocoa纯净"之外,它仍然比其他解决方案要短得多 :)

2
它会阻塞线程。如果在主线程中调用它,你实际上是在终止运行循环,应用程序将会看起来“死掉”。 - pestilence669
4
那就不要从主线呼叫。 - Charlie

1
如果您不介意使用异步解决方案,这里有一个:
[[NSOperationQueue currentQueue] addOperationWithBlock:^{
    [self doStuffAfterWaiting];
}];

0

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