SwiftUI - How to pass EnvironmentObject into View Model?

后端 未结 5 1993
甜味超标
甜味超标 2020-12-08 18:56

I\'m looking to create an EnvironmentObject that can be accessed by the View Model (not just the view).

The Environment object tracks the application session data, e

5条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-08 19:46

    I choose to not have a ViewModel. (Maybe time for a new pattern?)

    I have setup my project with a RootView and some child views. I setup my RootView with a App object as the EnvironmentObject. Instead of the ViewModel accessing Models, all my views access classes on App. Instead of the ViewModel determining the layout, the view hierarchy determine the layout. From doing this in practice for a few apps, I've found my views are staying small and specific. As an over simplification:

    class App {
       @Published var user = User()
    
       let networkManager: NetworkManagerProtocol
       lazy var userService = UserService(networkManager: networkManager)
    
       init(networkManager: NetworkManagerProtocol) {
          self.networkManager = networkManager
       }
    
       convenience init() {
          self.init(networkManager: NetworkManager())
       }
    }
    
    struct RootView {
        @EnvironmentObject var app: App
    
        var body: some View {
            if !app.user.isLoggedIn {
                LoginView()
            } else {
                HomeView()
            }
        }
    }
    
    struct HomeView: View {
        @EnvironmentObject var app: App
    
        var body: some View {
           VStack {
              Text("User name: \(app.user.name)")
              Button(action: { app.userService.logout() }) {
                 Text("Logout")
              }
           }
        }
    }
    

    In my previews, I initialize a MockApp which is a subclass of App. The MockApp initializes the designated initializers with the Mocked object. Here the UserService doesn't need to be mocked, but the datasource (i.e. NetworkManagerProtocol) does.

    struct HomeView_Previews: PreviewProvider {
        static var previews: some View {
            Group {
                HomeView()
                    .environmentObject(MockApp() as App) // <- This is needed for EnvironmentObject to treat the MockApp as an App Type
            }
        }
    
    }
    

提交回复
热议问题