我正在尝试理解在调用 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"
}
}
}
- 在第一个示例中,为什么代码在
for try await line in url.lines {
这一行之后在主线程上运行? - 为什么在第二个示例中同样是在那一行之后的代码却没有在主线程上运行?
如果没有运行代码并设置断点来检查我所在的线程,我该如何知道这些问题的答案?
显然,主要问题在于我想确保在主线程上更新@State变量以使视图正常工作,但是,如果不清楚这个概念,很难设计适当的模式。