我想在某个点暂停我的应用程序。换句话说,我希望我的应用程序执行代码,但在某一点上,暂停4秒,然后继续执行其余的代码。我该怎么做呢?

我用的是Swift。


当前回答

NSTimer

@nneonneo的回答建议使用NSTimer,但没有说明如何使用。这是基本语法:

let delay = 0.5 // time in seconds
NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(myFunctionName), userInfo: nil, repeats: false)

这里有一个非常简单的项目来展示如何使用它。当一个按钮被按下时,它会启动一个计时器,在延迟半秒后调用一个函数。

import UIKit
class ViewController: UIViewController {

    var timer = NSTimer()
    let delay = 0.5
    
    // start timer when button is tapped
    @IBAction func startTimerButtonTapped(sender: UIButton) {

        // cancel the timer in case the button is tapped multiple times
        timer.invalidate()

        // start the timer
        timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
    }

    // function to be called after the delay
    func delayedAction() {
        print("action has started")
    }
}

使用dispatch_time(如Palle的回答)是另一个有效的选项。然而,这很难取消。使用NSTimer,在延迟事件发生之前取消它,你所需要做的就是调用

timer.invalidate()

不建议使用sleep,特别是在主线程上,因为它会停止线程上正在完成的所有工作。

在这里可以看到我更完整的答案。

其他回答

如果从UI线程调用,sleep会锁住你的程序,可以考虑使用NSTimer或分派计时器。

但是,如果你真的需要延迟当前线程:

do {
    sleep(4)
}

这使用了UNIX中的睡眠函数。

你也可以用Swift 3这样做。

像这样执行延迟后的功能。

override func viewDidLoad() {
    super.viewDidLoad()

    self.perform(#selector(ClassName.performAction), with: nil, afterDelay: 2.0)
}


     @objc func performAction() {
//This function will perform after 2 seconds
            print("Delayed")
        }

在Swift 3.0中尝试以下实现

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

使用

delayWithSeconds(1) {
   //Do something
}

swift 3.0中不同方法的比较

1. 睡眠

此方法没有回调。将代码直接放在这一行之后,在4秒内执行。它将阻止用户迭代UI元素,如测试按钮,直到时间结束。虽然按钮在睡眠开始时有点冻结,但其他元素,如活动指示器仍在旋转而没有冻结。在休眠期间不能再次触发此操作。

sleep(4)
print("done")//Do stuff here

2. 调度,执行和定时器

这三种方法的工作原理类似,它们都运行在后台线程上,并带有回调,只是语法和功能略有不同。

分派通常用于在后台线程上运行一些东西。它有回调函数作为函数调用的一部分

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4), execute: {
    print("done")
})

Perform实际上是一个简化的计时器。它设置一个具有延迟的计时器,然后通过选择器触发函数。

perform(#selector(callback), with: nil, afterDelay: 4.0)

func callback() {
    print("done")
}}

最后,timer还提供了重复回调的能力,这在这个例子中是没有用的

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


func callback() {
    print("done")
}}

对于这三种方法,当你点击按钮触发它们时,UI不会冻结,你可以再次点击它。如果你再次点击按钮,另一个计时器将被设置,回调将被触发两次。

总之

这四种方法单独使用都不够好。Sleep将禁用用户交互,所以屏幕“冻结”(不是真的),并导致糟糕的用户体验。其他三个方法不会冻结屏幕,但您可以多次触发它们,大多数情况下,您希望等待,直到您得到回调才允许用户再次进行调用。

所以更好的设计是使用三种带有屏幕阻塞的异步方法之一。当用户点击按钮时,用半透明的视图覆盖整个屏幕,顶部有一个旋转的活动指示器,告诉用户按钮点击正在被处理。然后删除回调函数中的视图和指示器,告诉用户操作已正确处理,等等。

NSTimer

@nneonneo的回答建议使用NSTimer,但没有说明如何使用。这是基本语法:

let delay = 0.5 // time in seconds
NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(myFunctionName), userInfo: nil, repeats: false)

这里有一个非常简单的项目来展示如何使用它。当一个按钮被按下时,它会启动一个计时器,在延迟半秒后调用一个函数。

import UIKit
class ViewController: UIViewController {

    var timer = NSTimer()
    let delay = 0.5
    
    // start timer when button is tapped
    @IBAction func startTimerButtonTapped(sender: UIButton) {

        // cancel the timer in case the button is tapped multiple times
        timer.invalidate()

        // start the timer
        timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
    }

    // function to be called after the delay
    func delayedAction() {
        print("action has started")
    }
}

使用dispatch_time(如Palle的回答)是另一个有效的选项。然而,这很难取消。使用NSTimer,在延迟事件发生之前取消它,你所需要做的就是调用

timer.invalidate()

不建议使用sleep,特别是在主线程上,因为它会停止线程上正在完成的所有工作。

在这里可以看到我更完整的答案。