为了防止误解问题:我很清楚,不允许从后台线程为 @Published
属性发布
新值。但这不是我的问题。
我想知道从后台线程获取/读取@Published
属性的值(不更改它)是否可以。如果没有,为什么? 例如:
class ViewModel: ObservableObject {
@Published var name: String = ""
func saveName() {
DispatchQueue.global().async {
print("Getting name from background: \(self.name)") // <-- HERE
}
}
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
VStack {
TextField("Name", text: $viewModel.name)
Button("Submit") {
viewModel.saveName()
}
}
}
}
直觉上感觉不对,但是
这是一个有效的代码吗?不,它不是线程安全的。显然,您没有做任何事情来体现非线程安全行为,但如果该属性是
@Published
,则可能您打算对其进行变异,从而体现出潜在的问题。您注意到您收到了:
没有编译错误如果您将“严格并发检查”构建设置设置为“完成”,则收到警告。
如果您将
ObservableObject
与主要参与者隔离(按照 WWDC 2021 的视频Discover concurrency in SwiftUI中的建议),您现在将收到有关从后台队列访问
name
的警告,现在已与主要参与者隔离.底线,如果您有一个属性被发布到 UI,最简单的方法是将该属性与主要参与者隔离,编译器将(至少使用“严格并发检查”的“完整”设置)警告您误用。