I have the following code:
import SwiftUI
import Observation
struct ContentView: View {
@State var vm = ViewModel()
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}
@Observable class ViewModel {
struct TestInfo {
var myId:Int
}
@MainActor var info:TestInfo?
func setupInfo() async {
var tmp:TestInfo?
await CoreData.shared.context.perform {
/// some core data work and then we set tmp
tmp = TestInfo(myId: ....)
}
await MainActor.run {
info = tmp /// ERROR: Reference to captured var 'tmp' in concurrently-executing code
}
}
}
I would like to know how to fix this error. I setup tmp
within the core data context closure and would like to then set info
to tmp
.
Your ViewModel
should be annotated @MainActor
since it drives the UI. This will ensure that setupInfo
is on the main actor, and remove the need for the MainActor.run
that is causing trouble.
Furthermore, you should not set up a tmp
and modify it elsewhere. Instead, let perform
return your value:
self.info = CoreData.shared.context.perform {
/// some core data work
return TestInfo(myId: ....)
}
Altogether it would look like this:
@MainActor @Observable class ViewModel {
struct TestInfo {
var myId:Int
}
var info:TestInfo?
func setupInfo() async {
info = await CoreData.shared.context.perform {
/// some core data work and then we set tmp
tmp = TestInfo(myId: ....)
}
}
}