在我的SwiftUI应用中,我有一个如下的入口点
@main
struct SomeApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
AppContainerView()
}
}
}
struct AppContainerView: View {
@StateObject var appState = AppState()
var body: some View {
if appState.isLoggedIn && appState.hasSeenOnboarding {
TabContainerView()
} else {
LandingView().environmentObject(appState)
}
}
}
我可以像这样更新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?还是更好的方法?
答案 0 :(得分:1)
一种可能的选择是将AppState
传递到ChildViewModel
并直接在视图模型中执行AppState
更新。
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 {
...
}
}
注意
您可能希望查看依赖项注入,以使其更加简洁。这是一个可能的示例:Simple Dependency Injection using @propertyWrapper。