我想在某个点暂停我的应用程序。换句话说,我希望我的应用程序执行代码,但在某一点上,暂停4秒,然后继续执行其余的代码。我该怎么做呢?
我用的是Swift。
我想在某个点暂停我的应用程序。换句话说,我希望我的应用程序执行代码,但在某一点上,暂停4秒,然后继续执行其余的代码。我该怎么做呢?
我用的是Swift。
当前回答
在Swift 3.0中尝试以下实现
func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
completion()
}
}
使用
delayWithSeconds(1) {
//Do something
}
其他回答
作为之前建议的选项的替代解决方案,您可以使用基于DispatchGroup类的延迟,它被设计为同步多个异步任务的执行:
print("Start")
print(Date())
let delay = DispatchTimeInterval.seconds(3)
let group = DispatchGroup()
group.enter()
_ = group.wait(timeout: .now() + delay)
print("Finish")
print(Date())
其中,enter()方法用于显式地指示组代码的执行已经开始,wait(timeout:)方法用于等待组任务完成。当然,在本例中,这种情况永远不会发生,为此指定了一个超时,它等于所需的延迟。
使用它作为现成的帮手非常方便:
public class DispatchWait {
private init () { }
public static func `for` (_ interval: DispatchTimeInterval) {
let group = DispatchGroup()
group.enter()
_ = group.wait(timeout: .now().advanced(by: interval))
}
}
使用DispatchWait的示例:
print("Start")
print(Date())
DispatchWait.for(.seconds(3))
print("Finish")
print(Date())
不幸的是,我不能说这个延迟的准确性是多少,以及wait(timeout:)方法允许在指定的延迟之后继续执行程序的概率是多少。
此外,此解决方案允许您延迟当前队列中的代码,而不必在单独的闭包中执行它。
我同意Palle的观点,在这里使用dispatch_after是一个很好的选择。但是您可能不喜欢GCD调用,因为编写它们非常烦人。相反,你可以添加这个方便的助手:
public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) {
let dispatchTime = DispatchTime.now() + seconds
dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure)
}
public enum DispatchLevel {
case main, userInteractive, userInitiated, utility, background
var dispatchQueue: DispatchQueue {
switch self {
case .main: return DispatchQueue.main
case .userInteractive: return DispatchQueue.global(qos: .userInteractive)
case .userInitiated: return DispatchQueue.global(qos: .userInitiated)
case .utility: return DispatchQueue.global(qos: .utility)
case .background: return DispatchQueue.global(qos: .background)
}
}
}
现在你只需在后台线程上延迟你的代码,就像这样:
delay(bySeconds: 1.5, dispatchLevel: .background) {
// delayed code that will run on background thread
}
在主线程上延迟代码甚至更简单:
delay(bySeconds: 1.5) {
// delayed code, by default run in main thread
}
如果你喜欢一个框架,也有一些更方便的功能,然后签出handysswift。你可以通过SwiftPM将它添加到你的项目中,然后像上面的例子一样使用它:
import HandySwift
delay(by: .seconds(1.5)) {
// delayed code
}
这是添加延迟的一种更简单的方式,不会影响线程执行。
let continueTime: Date = Calendar.current.date(byAdding: .second, value: 30, to: Date())!
while (Date() < continueTime) {
//DO NOTHING
}
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,特别是在主线程上,因为它会停止线程上正在完成的所有工作。
在这里可以看到我更完整的答案。
如果需要将延迟设置为小于1秒,则不需要设置.seconds参数。我希望这对某些人有用。
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
// your code hear
})