如何在Swift 3中编程延迟

在早期版本的Swift中,可以使用以下代码创建延迟:

let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 4 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
//put your code which should be executed with a delay here
}

但是现在,在Swift 3中,Xcode自动更改了6个不同的东西,但随后出现以下错误:“无法将DispatchTime.now转换为期望值dispatch_time_t,也就是UInt64。”

在Swift 3中,如何在运行一段代码序列之前创建一个延迟?

349042 次浏览

经过大量的研究,我终于明白了这一点。

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Change `2.0` to the desired number of seconds.
// Code you want to be delayed
}

这在Swift 3和Swift 4中创建了理想的“等待”效果。

灵感来自这个答案的一部分。

试试下面在Swift 3.0及以上版本中实现的函数

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

使用

delayWithSeconds(1) {
//Do something
}

我喜欢单行符号的GCD,它更优雅:

    DispatchQueue.main.asyncAfter(deadline: .now() + 42.0) {
// do stuff 42 seconds later
}

此外,在iOS 10中我们有新的定时器方法,例如块初始化器:

(因此延迟的行动可能会被取消)

    let timer = Timer.scheduledTimer(withTimeInterval: 42.0, repeats: false) { (timer) in
// do stuff 42 seconds later
}

Btw,请记住:默认情况下,timer被添加到默认的运行循环模式。这意味着当用户与应用程序的UI交互时(例如,当滚动UIScrollView时),计时器可能会被冻结。 你可以通过在特定的运行循环模式中添加定时器来解决这个问题:

RunLoop.current.add(timer, forMode: .common)

在这个博客文章你可以找到更多细节。

// x秒后运行函数

public static func runThisAfterDelay(seconds: Double, after: @escaping () -> Void) {
runThisAfterDelay(seconds: seconds, queue: DispatchQueue.main, after: after)
}


public static func runThisAfterDelay(seconds: Double, queue: DispatchQueue, after: @escaping () -> Void) {
let time = DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
queue.asyncAfter(deadline: time, execute: after)
}

/ /使用:-

runThisAfterDelay(seconds: x){
//write your code here
}

试试下面的延迟代码

//MARK: First Way


func delayForWork() {
delay(3.0) {
print("delay for 3.0 second")
}
}


delayForWork()

// MARK: Second Way


DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// your code here delayed by 0.5 seconds
}

一种方法是使用DispatchQueue.main.asyncAfter,就像很多人回答的那样。

另一种方法是使用perform(_:with:afterDelay:)详情请点击这里

perform(#selector(delayedFunc), with: nil, afterDelay: 3)


@IBAction func delayedFunc() {
// implement code
}

最常用的是asyncAfter()Timer。但是如果阻塞线程是可以的,那么有一个选项:

sleep(3) // in seconds
usleep   // in 1/million of second

对于异步编程(Swift 5.5),在func中暂停是这样的:

func someAsyncFunc() async {
await Task.sleep(2_000_000_000)  // Two seconds
// Code to be executed with a delay here
}