Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing environment object between non-view classes in SwiftUI

I understand that EnvironmentObject property wrapper can be used to pass around objects to views. I have a session object which I am passing around to my views. Now I have a requirement to pass this into one of my model classes (i.e., non-view). Ideally, this model (receiving the session object) is instantiated as a StateObject.

struct CreditDetailsView: View {
  @EnvironmentObject var session: Session
  @StateObject var transactionsModel = TransactionsModel(token: session.token)

The code above will not work (understandably) because:

cannot use instance member 'session' within property initializer; property initializers run before 'self' is available

Any suggestions on how I can pass in the session into TransactionsModel?

like image 869
Pradyot Avatar asked May 27 '21 03:05

Pradyot


2 Answers

The best way that I've found to do this (because you cannot have an optional StateObject) is:

struct CreditDetailsView: View {
  @EnvironmentObject var session: Session
  @StateObject var localModel = LocalModel()
  
  var body: some View {
    SomeChildView()
      .onAppear {
        localModel.transactionModel = TransactionModel(token: session.token)
      }
  }

  class LocalModel: ObservableObject {
    @Published transactionModel: TransactionModel?
  }
}
like image 33
Jason Bobier Avatar answered Sep 20 '22 22:09

Jason Bobier


Try initializing the StateObject in an .onAppear() prop to a child view, like this:

struct CreditDetailsView: View {
  @EnvironmentObject var session: Session
  @StateObject var transactionsModel: TransactionModel?
  
  var body: some View {
    SomeChildView()
      .onAppear(perform: {
        transactionModel = TransactionModel(token: session.token)
      })
  }
}

This way, the variable is initialized when the view renders on the screen. It doesn't matter much which child view you add the onAppear prop to, as long as it is rendered as soon as the parent does.

like image 197
Finley Avatar answered Sep 20 '22 22:09

Finley