gpt4 book ai didi

ios - 执行 `await` 后的 Swift 任务和等待/异步队列?

转载 作者:行者123 更新时间:2023-12-05 03:28:53 26 4
gpt4 key购买 nike

我试图了解调用 Task { ... } 时的规则是什么,并且在该任务中,根据线程调用 await

这个例子有效:

struct TaskTestView: View {

let url = URL(string: "https://www.google.com")!
@State private var message = "Loading..."

var body: some View {
Text(message)
.task {
/// on MAIN THREAD
do {
var receivedLines = [String]()
for try await line in url.lines {
/// on MAIN THREAD
receivedLines.append(line)
message = "Received \(receivedLines.count) lines"
}
} catch {
message = "Failed to load"
}
}
}
}

这不是:

struct TaskTestView: View {

@StateObject var model = TaskTestViewModel()

var body: some View {
Text(model.message)
.task {
/// - here it is on main thread
await model.refresh()
/// - here it is NOT on main thread
print("after refresh: on main?")
}
}
}

class TaskTestViewModel:ObservableObject {

let url = URL(string: "https://www.google.com")!
@Published private(set) var message = "Loading..."

func refresh() async {

do {
var receivedLines = [String]() // on main thread
for try await line in url.lines {
receivedLines.append(line) // NOT on main thread
message = "Received \(receivedLines.count) lines"
}
} catch {
message = "Failed to load"
}

}

}
  1. 为什么代码在第一个示例中 for try await line in url.lines { 行之后在主线程上运行?
  2. 为什么代码不在同一行之后但在第二个示例中的主线程上运行?

如果不运行代码并设置断点来检查我所在的线程,我怎么知道这些问题的答案?

显然,这里的主要问题是我想确保更新 main 上的 @State 变量,以便 View 正常工作,但是,如果这个概念不清晰,就很难设计出合适的模式。

最佳答案

关于“延续”将在哪个线程上运行没有明确的规定。 WWDC 2021 视频 Swift concurrency: Behind the scenes讨论延续以及暂停点之后的线程可能与之前的线程有何不同。

尝试使用传统的调试语句或断点对其进行诊断可能会令人沮丧。我遇到过插入几行完全不相关的调试代码会改变连续线程行为的情况。底线是,除非您另有说明,否则可以自由决定延续将在哪个线程上运行,并且有时可能会出乎意料。

但是,如果您想确保您的可观察对象在主线程上更新,您可以使用 @MainActor 限定符:

@MainActor
class TaskTestViewModel: ObservableObject {
...
}

关于ios - 执行 `await` 后的 Swift 任务和等待/异步队列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71149249/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com