如何在Swift 2.2中让程序休眠几毫秒?

88
请问有人能告诉我如何在Swift 2.2中使用sleep()来暂停几毫秒吗?
while (true){
    print("sleep for 0.002 seconds.")
    sleep(0.002) // not working
}

但是

while (true){
    print("sleep for 2 seconds.")
    sleep(2) // working
}

它正在工作。


1
在轮询的情况下,线程休眠或让出是有效的。许多接口不提供通知,因此您必须定期检查即将发生的异步更改。如果在检查之间不暂停线程,则会不必要地使CPU负担过重,并且可能会阻塞您正在等待的进程。 - absmiths
1
sleep()函数以int类型的参数作为输入。因此,sleep(0.002)将不会休眠任何时间。请使用usleep(nanoseconds)代替。 - Mark Berner
对于那些想要使用Swift 5.5的async & await sleep的人,请参考来自不同帖子的答案。 - George
7个回答

155

usleep() 函数的参数单位是微秒

usleep(1000000) //will sleep for 1 second
usleep(2000) //will sleep for .002 seconds

或者

 let ms = 1000
 usleep(useconds_t(2 * ms)) //will sleep for 2 milliseconds (.002 seconds)

let second: Double = 1000000
usleep(useconds_t(0.002 * second)) //will sleep for 2 milliseconds (.002 seconds)

UInt32(0.002) 是 0。应该写成 usleep(UInt32(0.002 * second)) - Hans Terje Bakke
在 macOS 11.6 上,输入命令 "man sleep" 会提示: "usleep() 函数已过时,请改用 nanosleep(2)。" - ma11hew28

21

我认为在当前的Swift语法中,比usleep解决方案更优雅的是:

Thread.sleep(forTimeInterval: 0.002)

sleep(forTimeInterval:) 只是调用了 nanosleep() 吗? - ma11hew28
2
这些函数属于不同的API层:nanosleep是系统函数,属于Darwin的一部分,而Thread则属于 Foundation。在旧版的iOS / macOS中,它可能在底层使用usleep,现在可能正在使用nanosleep。无论如何,在导入Foundation时不需要使用nanosleep,它只可能需要用于其他语言,这些语言无法使用Foundation,但仍可以访问Darwin,因为它是用C编写的。 - Phil Dukhov
好的,谢谢。 :-) - ma11hew28

10

使用 func usleep(_: useconds_t) -> Int32 (导入 DarwinFoundation ...)

重要提示: usleep() 接受的是百万分之一秒,所以usleep(1000000)将会休眠1秒钟。


3
usleep() 函数的参数单位是微秒,因此 usleep(1000000) 将会让程序休眠 1 秒钟。 - Elijah
这个 ^ 这个 ^ 这个 ^ - ScottyBlades

4

非阻塞的usleep解决方案:

DispatchQueue.global(qos: .background).async {
    let second: Double = 1000000
    usleep(useconds_t(0.002 * second)) 
    print("Active after 0.002 sec, and doesn't block main")
    DispatchQueue.main.async{
        //do stuff in the main thread here
    }
}

4

如果你真的需要让程序休眠,可以尝试使用usleep,就像@user3441734的回答所建议的那样。

然而,你也许需要考虑是否休眠是最好的选择:它就像暂停按钮,当程序在运行时会被冻结并且无法响应。

你可以考虑使用NSTimer

 //Declare the timer
 var timer = NSTimer.scheduledTimerWithTimeInterval(0.002, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
 self, selector: "update", userInfo: nil, repeats: true)



func update() {
    // Code here
}

有时候暂停一些后台任务是个好主意......使用 sleep 和 usleep 可能会是非常有帮助的、易于采用和不需要花费很多的解决方案。不幸的是,正确使用 sleep 或 usleep 的情况非常罕见。通常最好避免使用 :-) - user3441734
如果您暂停事件线程,它只会冻结应用程序,这总是一个可怕的想法。除UI之外的工作应该在该线程之外完成。正常使用usleep只会导致当前线程阻塞。 - absmiths
嗯,如果你在应用程序的高级部分调用 usleep,那么这很可能是一个不好的迹象。首先,它可能会阻塞 GCD 队列。只有在苹果提供的抽象确实不适合你需要做的事情时才使用。 - sudo

2

或者:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.002) {
   /*Do something after 0.002 seconds have passed*/
}

我没有深入了解它的工作原理,但似乎在Objective-C(和Swift中),该代码每个dTime会产生一个新的线程而不销毁之前的线程。因此,在最好的情况下,您会浪费设备的内存,在最坏的情况下,应用程序由于巨大的内存消耗而崩溃(取决于循环计数)。 - Vyachaslav Gerchicov

0

例如更改按钮的透明度值

 sender.alpha = 0.5
 
 DispatchQueue.main.asyncAfter(deadline:.now() + 0.2){
             sender.alpha = 1.0
         }

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