SwiftUI Using @MainActor with EnvironmentKey

619 Views Asked by At

I Use @MainActor with view model class as shown in the code below, when I tried to add Environment Key for the model the following error appear: "Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context" and code not compile until I remove the @MainActor from the class. Is that possible to use both @MainActor and EnvironmentKey for same class.

View model class:

extension HomeView {
@MainActor
    internal final class ViewModel: ObservableObject {
      // More code here...
   }
}

EnvironmentKey for view model:

struct HomeViewModelKey: EnvironmentKey {
    static var defaultValue = HomeView.ViewModel()
}

extension EnvironmentValues {
    var homeViewModel: HomeView.ViewModel {
    get { self[HomeViewModelKey.self] }
    set { self[HomeViewModelKey.self] = newValue }
  }
}
2

There are 2 best solutions below

1
On BEST ANSWER

Have you tried adding the main actor attribute to your environment key properties as follows?:

View Model Class:

extension HomeView {
    @MainActor
    internal final class ViewModel: ObservableObject {
        // More code here...
    }
}

EnvironmentKey for view model:

struct HomeViewModelKey: EnvironmentKey {
    @MainActor
    static var defaultValue = HomeView.ViewModel()
}

extension EnvironmentValues {
    @MainActor
    var homeViewModel: HomeView.ViewModel {
        get { self[HomeViewModelKey.self] }
        set { self[HomeViewModelKey.self] = newValue }
    }
}
5
On

You can use .environmentObject(Store.shared) for your store object that loads the model structs into @Published properties. Usually it's a singleton .shared with another singleton for previewing .preview.