我正在学习Swift 的async
, await
, @MainActor
。
我想运行一个很长的过程并显示进度。
import SwiftUI
@MainActor
final class ViewModel: ObservableObject {
@Published var count = 0
func countUpAsync() async {
print("countUpAsync() isMain=\(Thread.isMainThread)")
for _ in 0..<5 {
count += 1
Thread.sleep(forTimeInterval: 0.5)
}
}
func countUp() {
print("countUp() isMain=\(Thread.isMainThread)")
for _ in 0..<5 {
self.count += 1
Thread.sleep(forTimeInterval: 0.5)
}
}
}
struct ContentView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
VStack {
Text("Count=\(viewModel.count)")
.font(.title)
Button("Start Dispatch") {
DispatchQueue.global().async {
viewModel.countUp()
}
}
.padding()
Button("Start Task") {
Task {
await viewModel.countUpAsync()
}
}
.padding()
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
当我点击“开始调度”按钮时,“计数”会更新,但会收到警告:
不允许从后台线程发布更改;确保在模型更新时从主线程发布值(通过接收(on :) 等运算符)。
我认为类ViewModel
是@MainActor
,count
属性是在Main
线程中操作的,但不是。我应该使用DispatchQueue.main.async{}
更新count
吗@MainActor
?
当我点击“开始任务”按钮时,按下按钮直到countupAsync()
完成并且不更新屏幕上的计数。
什么是最好的解决方案?