Mvvm ViewModel Async Func完成时如何从子视图更新EnvironmentObject
在我的SwiftUI应用程序中,我有一个入口点,如下所示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
@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 {
...
}
}