【发布时间】:2022-08-19 12:36:49
【问题描述】:
我正在维护一个将使用 SwiftUI 的遗留代码库。我正在使用新的可刷新 api:https://developer.apple.com/documentation/SwiftUI/View/refreshable(action:)。他们强迫你使用异步等待有点烦人,因为我有一部分刷新代码不能完全异步等待。
我不能对此代码使用异步等待的原因是应用程序通过网络套接字.应用程序手动匹配对请求的响应,然后在它们到达时调用闭包。我不相信完全重写为异步等待是可能的。
我有一个最终将始终返回结果的闭包。当结果到来时,微调器应该消失。这是我可怕的异步等待包装器(简化):
/// Terrible way of adding async await support
func sendAsync() async {
try! await Task {
var future: Void? = nil
self.onReceive = { _ in
future = ()
}
while true {
if future != nil {
return
}
// This is 10 ms
try await Task.sleep(nanoseconds: 10_000_000)
}
}.value
}
所以这是一个基于自旋锁的异步等待包装器。我想知道是否有更好的方法来做到这一点。我包裹在Task 中,它不会以这种方式在主线程上运行。
是否有一些现有的异步等待包装器等待值非零然后唤醒? refreshable 是否有不同的 api不是需要异步等待?
-
\“应用程序手动匹配对请求的响应,然后在它们到达时调用闭包。我认为这不可能完全重写为异步等待。\”也许这应该是你的问题?听起来像我是可能,使用通常的不安全的延续包装。
-
@matt 我不知道继续,但我目前正在使用 withCheckedContinuation,这太棒了!我知道有一个真正让它异步等待的起点,谢谢你的提示
-
是的,
withCheckedContinuation。或者,如果你愿意,这闻起来有点像AsyncSequence(在这种情况下你会使用AsyncStream)。 -
WWDC 2021 视频Meet AsyncSequence。
-
除了您应该在发货前更改为
withUncheckedContinuation。