如何使用async/await在Swift 5.5中等待x秒

24

如何使用新的Swift 5.5 await关键字等待一段时间?

通常,使用完成处理程序时,您可以通过使用DispatchQueueasyncAfter(deadline:execute:)来实现以下内容:

func someLongTask(completion: @escaping (Int) -> Void) {
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
        completion(Int.random(in: 1 ... 6))
    }
}

someLongTask { diceRoll in
    print(diceRoll)
}

如何在Swift 5.5中使用asyncawait进行转换?

2个回答

54

iOS 16+ / macOS 13+

有一个更新的API,sleep(until:tolerance:clock:),使用方式如下:


有一个更新的API,sleep(until:tolerance:clock:),使用方式如下:
// 3 seconds
try await Task.sleep(until: .now + .seconds(3), clock: .continuous)

iOS <16 / macOS <13

你可以使用Task.sleep(nanoseconds:)等待一段特定的时间。这里所测量的时间是纳秒,而不是秒。

下面是一个例子:

func someLongTask() async -> Int {
    try? await Task.sleep(nanoseconds: 1 * 1_000_000_000) // 1 second
    return Int.random(in: 1 ... 6)
}

Task {
    let diceRoll = await someLongTask()
    print(diceRoll)
}

使用一个睡眠扩展可能更容易,这样你就可以直接传递秒数:

extension Task where Success == Never, Failure == Never {
    static func sleep(seconds: Double) async throws {
        let duration = UInt64(seconds * 1_000_000_000)
        try await Task.sleep(nanoseconds: duration)
    }
}

现在这将被称为:

try await Task.sleep(seconds: 1)

请注意使用try调用睡眠函数。如果睡眠被取消,将抛出错误。如果您不关心是否被取消,可以只使用try?


这个问题已经修复了吗?在早期测试版中它实际上并没有起作用。 - matt
@matt,现在我的运行正常,早期测试版有什么问题? - George
任何超过几纳秒的时间我们实际上不会睡觉。 :) 请参阅我 https://dev59.com/A1EG5IYBdhLWcg3wU6VP#67929769 后的评论。不管怎样,很高兴听到它现在可以工作了! - matt
很酷!好知道。 - matt
@matt,答案中链接的sleep方法文档中写道:“当成功和失败都不是时可用。”在没有这个where子句的情况下,我无法编译它,所以我找到了这个。如果有一个限制更少的版本,那会更好。 - George
显示剩余3条评论

10
从iOS 16开始,您可以直接使用.seconds,如下所示:
try await Task.sleep(for: .seconds(10))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接