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

我用的是Swift。


当前回答

在Swift 3.0中尝试以下实现

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

使用

delayWithSeconds(1) {
   //Do something
}

其他回答

这是最简单的

    delay(0.3, closure: {
        // put her any code you want to fire it with delay
        button.removeFromSuperview()   
    })

我同意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和Xcode 10.1中

你总共有4种方法来延迟。在这些选项中,首选选项1是在一段时间后调用或执行函数。sleep()是使用最少的情况。

选项1。

DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    self.yourFuncHere()
}
//Your function here    
func yourFuncHere() {

}

第二个选项。

perform(#selector(yourFuncHere2), with: nil, afterDelay: 5.0)

//Your function here  
@objc func yourFuncHere2() {
    print("this is...")
}

选项3。

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

//Your function here  
@objc func yourFuncHere3() {

}

选项4。

sleep(5)

如果你想在一段时间后调用一个函数来执行一些东西,不要使用sleep。

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将禁用用户交互,所以屏幕“冻结”(不是真的),并导致糟糕的用户体验。其他三个方法不会冻结屏幕,但您可以多次触发它们,大多数情况下,您希望等待,直到您得到回调才允许用户再次进行调用。

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

如果你的代码已经在后台线程中运行,在Foundation: thread .sleep(forTimeInterval:)中使用这个方法暂停线程。

例如:

DispatchQueue.global(qos: .userInitiated).async {

    // Code is running in a background thread already so it is safe to sleep
    Thread.sleep(forTimeInterval: 4.0)
}

(当代码在主线程上运行时,请参阅其他答案以获得建议。)