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

我用的是Swift。


当前回答

作为之前建议的选项的替代解决方案,您可以使用基于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:)方法允许在指定的延迟之后继续执行程序的概率是多少。

此外,此解决方案允许您延迟当前队列中的代码,而不必在单独的闭包中执行它。

其他回答

我认为最简单和最新的4秒计时器方法是:

Task { 
    // Do something

    // Wait for 4 seconds
    try await Task.sleep(nanoseconds: 4_000_000_000) 

}

它使用了Swift 5.5的新并发。

我同意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
}

你可以创建扩展来轻松使用延迟函数(语法:Swift 4.2+)

extension UIViewController {
    func delay(_ delay:Double, closure:@escaping ()->()) {
        DispatchQueue.main.asyncAfter(
            deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
    }
}

如何在UIViewController中使用

self.delay(0.1, closure: {
   //execute code
})

在Swift 3.0中尝试以下实现

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

使用

delayWithSeconds(1) {
   //Do something
}

如果需要将延迟设置为小于1秒,则不需要设置.seconds参数。我希望这对某些人有用。

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
        // your code hear
})