admin管理员组

文章数量:1287607

I have a parent view and a child view. The child view requires a view model, and the view model requires an environment variable. Is there a way to avoid reinstantiating my view model every time SwiftUI renders the body? Is my overall approach to injecting the view model fine?

    struct SettingsView: View {
    
      @Environment(\.userSessionRepository) var sessionManager
    
      private var accountViewModel: AccountSectionViewModel?
    
      var body: some View {
          NavigationStack {
              Form {
                  AccountSectionView(viewModel: createAccountViewModel())
                  AppearanceSectionView()
                  HelpAndSupportSectionView()
              }
          }
      }
    
      private func createAccountViewModel() -> AccountSectionViewModel {
          return AccountSectionViewModel(
              coreDataClearing: CoreDataClearingManager(),
              sessionManager: sessionManager
          )
      }
  }

I have a parent view and a child view. The child view requires a view model, and the view model requires an environment variable. Is there a way to avoid reinstantiating my view model every time SwiftUI renders the body? Is my overall approach to injecting the view model fine?

    struct SettingsView: View {
    
      @Environment(\.userSessionRepository) var sessionManager
    
      private var accountViewModel: AccountSectionViewModel?
    
      var body: some View {
          NavigationStack {
              Form {
                  AccountSectionView(viewModel: createAccountViewModel())
                  AppearanceSectionView()
                  HelpAndSupportSectionView()
              }
          }
      }
    
      private func createAccountViewModel() -> AccountSectionViewModel {
          return AccountSectionViewModel(
              coreDataClearing: CoreDataClearingManager(),
              sessionManager: sessionManager
          )
      }
  }
Share Improve this question edited Feb 23 at 15:04 Joakim Danielson 52.1k5 gold badges33 silver badges71 bronze badges asked Feb 23 at 8:32 user_personuser_person 1251 gold badge2 silver badges7 bronze badges 5
  • 2 Why not just create it in AccountSectionView? If you do it in a @StateObject initialiser, it will only be created once throughout the lifetime of AccountSectionView. (assuming AccountSectionViewModel is an ObservableObject) – Sweeper Commented Feb 23 at 8:40
  • You need to learn Binding. View model objects won’t work. Try the tutorials. – malhal Commented Feb 23 at 9:19
  • @malhal What would binding accomplish here? AccountSectionView and SettingsView do not need to share any properties. I just want to be able to set the initial state outside of the AccountSectionView, so I can preview it. – user_person Commented Feb 23 at 10:23
  • 2 Do not create objects in the body – lorem ipsum Commented Feb 23 at 11:55
  • @user_person then pass in the account, e.g. AccountSectionView(account: account) however you are only supposed to pass it what is needed, e.g. MainSectionView(title: account.nam) – malhal Commented Feb 23 at 14:22
Add a comment  | 

1 Answer 1

Reset to default 1

You could try this approach using .onAppear, when you have @StateObject or if you pass a @ObservedObject var accountViewModel: AccountSectionViewModel from the parent View.

See also Monitoring data, or for iOS17+ Managing model data in your app using @Observable.

Don't try to use init() because the sessionManager will not be available at that time.

 struct SettingsView: View {
    @Environment(\.userSessionRepository) var sessionManager
    
 //    @StateObject private var accountViewModel = AccountSectionViewModel()
     @ObservedObject var accountViewModel: AccountSectionViewModel

      var body: some View {
          NavigationStack {
              Form {
                  AccountSectionView(viewModel: accountViewModel) // <-- here
                  AppearanceSectionView()
                  HelpAndSupportSectionView()
              }
          }
          .onAppear {
              // add the required elements
              accountViewModel.coreDataClearing = CoreDataClearingManager()
              accountViewModel.sessionManager = sessionManager
          }
      }
  }

本文标签: swiftView model is instantiated twiceStack Overflow