Dar*_*ren 9 async-await swift swift5 swiftui swift-concurrency
我想在函数完成后 5 秒继续触发它。
以前我会在函数末尾使用它:
Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { self.function() }
Run Code Online (Sandbox Code Playgroud)
但我想用Swift 5.5的async/await.
如果我使用这样的东西:
func loadInfo() async {
async let info = someOtherAsyncFunc()
self.info = try? await info
await Task.sleep(5_000_000_000)
await loadInfo()
}
Run Code Online (Sandbox Code Playgroud)
我收到一条警告,说它Function call causes an infinite recursion并不是真正可以取消的。
这编译得很好:
func loadInfo() async {
Task {
async let info = someOtherAsyncFunc()
self.info = try? await info
await Task.sleep(5_000_000_000)
if Task.isCancelled {
print("Cancelled")
}
else
{
print("Not cancelled")
await loadInfo()
}
}
}
Run Code Online (Sandbox Code Playgroud)
尽管它每 5 秒触发一次,但当我的SwiftUI视图被忽略时它会继续运行。我使用以下方法启动它:
.onAppear {
loadInfo()
}
Run Code Online (Sandbox Code Playgroud)
因为它都在同一个上运行Task,所以detached当视图被删除时,不应该全部取消吗?
实现这一目标的现代方法是什么async/await?
您可以将任务保存在@State变量中,然后在视图消失时取消任务onDisappear(perform:)。
工作示例:
struct ContentView: View {
@State private var info: String?
@State private var currentTask: Task<Void, Never>?
var body: some View {
NavigationView {
VStack {
Text(info ?? "None (yet)")
.onAppear(perform: loadInfo)
.onDisappear(perform: cancelTask)
NavigationLink("Other view") {
Text("Some other view")
}
}
.navigationTitle("Task Test")
}
.navigationViewStyle(.stack)
}
private func loadInfo() {
currentTask = Task {
async let info = someOtherAsyncFunc()
self.info = try? await info
await Task.sleep(5_000_000_000)
guard !Task.isCancelled else { return }
loadInfo()
}
}
private func cancelTask() {
print("Disappear")
currentTask?.cancel()
}
private func someOtherAsyncFunc() async throws -> String {
print("someOtherAsyncFunc ran")
return "Random number: \(Int.random(in: 1 ... 100))"
}
}
Run Code Online (Sandbox Code Playgroud)
async wait 的目的是让您以同步方式编写异步代码。所以你可以删除递归函数并简单地编写:
.task {
repeat {
// code you want to repeat
print("Tick")
try? await Task.sleep(for: .seconds(5)) // exception thrown when cancelled by SwiftUI when this view disappears.
} while (!Task.isCancelled)
print("Cancelled")
}
Run Code Online (Sandbox Code Playgroud)
我注意到打印刻度始终在主线程上,但是如果我将它移到它自己的异步函数中,那么它可以在不同的线程上正确运行。
| 归档时间: |
|
| 查看次数: |
6913 次 |
| 最近记录: |