I've got an ObservableObject
class that I am calling to via @StateObject
from my view. Inside that class is a function and the entire class is marked @MainActor
. In my view there is a TextField
with an onChange
modifier that has a perform calling to that function via viewModel.funcname
.
Xcode is complaining with an error of:
Converting function value of type '@MainActor (String) -> Void' to '(String) -> Void' loses global actor 'MainActor'
I've been researching this for hours now and have found little to nothing. Even Apple's own docs say to simply use await but that doesn't work, at least not the many ways I've tried it.
This is the code within my view:
TextField("", text: $viewModel.username)
.onChange(of: viewModel.username, perform: viewModel.editingChanged) // This is where the error occurs
This is the function in my class (remember that the entire class is marked @MainActor
):
func editingChanged(_ value: String) {
let jsonFetchUserExistsURL = URL(string: "https://blah.com")
let jsonFetchUserExistsTask = jsonFetch(jsonFetchUserExistsURL, defaultValue: [UserExists]())
guard isNetworkActive else { loadingAlert = true; return }
Task {
jsonFetchUserExistsTask.sink (receiveCompletion: { completion in
switch completion {
case .failure:
self.loadingState = .failed
case .finished:
self.checkUser()
}
},
receiveValue: { loadedUserExists in
self.userExists = loadedUserExists
}).store(in: &requests)
}
}
}
I have tried modifying the onChange
to read as follows:
.onChange(of: viewModel.username, perform: await viewModel.editingChanged)
.onChange(of: viewModel.username, perform: Task { await viewModel.editingChanged })
.onChange(of: viewModel.username, perform: Task.detached { await viewModel.editingChanged })
.onChange(of: viewModel.username, perform: DispatchQueue.main.async { viewModel.editingChanged })
The entire reason I marked the class @MainActor
is because Xcode complained that the function wasn't running on the main thread. It compiled but froze after it complained a few times in the console.
Nothing I've tried seems to change anything. Hoping someone can shed some light on this.
See my comment on the question about whether or not the @MainActor
strategy is the right way to address an underlying issue, but to directly address your compilation error, you can use this syntax, which compiles fine:
.onChange(of: viewModel.username) { viewModel.editingChanged($0) }