Hol*_*ene 3 task async-await swift swiftui
根据 Apple 文档,当视图消失时,任务将自动取消。{}
在视图消失、操作完成之前的某个时刻,SwiftUI 会自动取消任务。
为什么在这种情况下,当 ChildView 消失时,“loadData”方法中的任务没有取消?(当导航回“ParentView”时)
struct ChildView: View {
@State private var data: [Double] = []
private func loadData() async {
// Why isn't this Task automatically cancelled when the ChildView disappears?
// The Task is still executing in the background.
Task(priority: .background) {
// Simulating heavy data processing.
self.data = (1...3_000_000).map { _ in Double.random(in: -10...30) }
print("Task ended")
}
}
var body: some View {
Text("This is a child view")
.task { await loadData() }
}
}
struct ParentView: View {
var body: some View {
NavigationStack {
NavigationLink(destination: { ChildView() }) {
Text("Show child view")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
即使 ChildView 消失,“loadData”中的任务也会继续执行。当ChildView连续多次初始化时,它也会执行多次。
这可能会导致内存泄漏,尤其是在 ChildView 中使用带有 @Published 'data' 属性而不是 @State 属性的类时。在这种情况下使用 Task() 的正确实现是什么?
SwiftUI 确实取消了视图修饰符隐式创建的任务task,但该任务不执行“繁重的数据处理”。该任务仅创建一个要运行的子任务loadData。该子任务几乎立即完成。
这是因为它所做的只是通过使用loadData创建一个顶级任务Task { ... },而不执行其他任何操作。当你的视野消失时,loadData任务就已经完成了。然而,顶级任务执行所有“繁重的数据处理”,并且因为它是顶级任务(即不是任务的子任务),所以在取消loadData时它不会被取消。loadData
您不应该在此处创建顶级任务。把繁重的数据处理直接放在loadData.
此外,任务取消是合作性的 -loadData还应该检查Task.isCancelled并停止它正在做的事情。
private func loadData() async {
for _ in 1...3_000_000 {
if Task.isCancelled { // for example
break
}
self.data.append(Double.random(in: -10..<30))
}
print("Task ended")
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
702 次 |
| 最近记录: |