I have the following view model:
@MainActor
final class SomeViewModel {
func loadFromService() async {
do {
let dto = try await networkService.theServiceIneedHere()
//process dto
//state is a @Published property and observed by a SwiftUI view to update the UI.
state = .success(viewData)
} catch {
state = .failure(someError)
}
}
}
My question here is, if loadFromService is called from my SwiftUI view task method and my SwiftUI view is not marked as a @MainActor then is loadFromService() running on the MainActor’s thread? ie it is not isolated?
Is the following a better approach to the above code?
final class SomeViewModel {
func loadFromService() async {
do {
let dto = try await networkService.theServiceIneedHere()
await handleServiceSuccess(with:dto)
} catch {
await MainActor.run {
state = .failure(someError)
}
}
}
}
@MainActor
private func handleServiceSuccess(with: DTO) {
//process dto, update state here
state = .success(viewData)
}
In the second approach I feel, loadFromService is detached from Mainthread and only when we need to update the UI, we switch back to the main thread.
The short answer for your question:
So in your first example, the function in network service is executed on any thread and state is updated on main.
@MainActorof your viewModel affects the scope of viewModel not nested async functions called by this class.Regarding your View:
First approach would be my preferred way. Because then you don't need to switch to the main thread before updating any UI parameter (most likely @Published properties).
I'm not familiar with the new
@Observableyet but this is at least my suggestion for@ObservableObjectsince you store your properties as@Publishedand update them in view model.