Mvvm ViewModel Async Func完成时如何从子视图更新EnvironmentObject

Mvvm ViewModel Async Func完成时如何从子视图更新EnvironmentObject,mvvm,swiftui,Mvvm,Swiftui,在我的SwiftUI应用程序中,我有一个入口点,如下所示 @main struct SomeApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { AppContainerView() } } } 我可以像这样更新isLoggedIn class A

在我的SwiftUI应用程序中,我有一个入口点,如下所示

@main
struct SomeApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            AppContainerView()
        }
    }
}
我可以像这样更新
isLoggedIn

class AppState: ObservableObject {
    var cancellables: [AnyCancellable] = []
    private let userService: UserServiceProtocol
    init(userService: UserServiceProtocol = UserService()) {
        self.userService = userService
        subscribeForAuthChanges()
    }
    
    func subscribeForAuthChanges() {
        userService.authChangeSubject.sink(receiveValue: { [weak self] auth, user in
            print(auth)
            if user != nil {
                self?.isLoggedIn = true
            }
        }).store(in: &cancellables)
    }
    
    @Published var isLoggedIn = false
    @Published var hasSeenOnboarding = false
}
但是当涉及到
hasSeenOnboarding
时,需要在
LandingView
子视图之一的viewModel中完成某个网络调用后将其设置为true。我可以这样做

struct ChildView: View {
  @EnvironmentObject var appState: AppState
  @StateObject var viewModel = ChildViewModel()

  var body: some View {
    VStack {
      //...
    }.onReceive($viewModel.networkCallCompleted) { completed in
       self.appState.hasSeenOnboarding = completed
    }
  }
}

但这感觉不对……在使用MVVM时,有没有更好的选项可以从childView/viewModel更改appState?或者更好的方法?

一种可能的替代方法是将
AppState
传递给
ChildViewModel
,并直接在视图模型中执行
AppState
更新

struct ParentView: View {
  @EnvironmentObject var appState: AppState

  var body: some View {
    ChildView(viewModel: ChildViewModel(appState: appState))
  }
}

注意


您可能需要查看依赖项注入以使其更干净。下面是一个可能的示例:.

感谢这一点-尽管当我将@Published hasSeenOnboarding属性更改为@AppStorage(AppState.hasSeenOnboardingKey)var hasSeenOnboarding:Bool=false时,它不会为某些用户重新加载视图reason@jeh
@AppStorage
应仅在视图中使用(就像
@State
)。
struct ParentView: View {
  @EnvironmentObject var appState: AppState

  var body: some View {
    ChildView(viewModel: ChildViewModel(appState: appState))
  }
}
struct ChildView: View {
  @EnvironmentObject var appState: AppState
  @StateObject var viewModel: ChildViewModel

  var body: some View {
    ...
  }
}