Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write to a SwiftUI environment object from a class (-extension)

Tags:

ios

swift

swiftui

Given the following setup:

Environment Variable UserState

class UserState: ObservableObject {
    @Published var loggedIn = Auth.auth().currentUser != nil
}

UserState as a variable in SceneDelegate

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
   ...

   //creating the variable
   var userState = UserState()

   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
       window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(userState))
   }

   ...
}

I can now perfectly read/write to this variable in SwiftUI views by declaring

struct ProfileTab: View {
    @EnvironmentObject var userState: UserState
    var body: some View {
        // here I could easily read/write to userState
    }
}

So far so good. But: What is the proper way to write to this variable outside of a SwiftUI view? E.g. from a class or class extension.

Example

extension AppDelegate {

    func something(loggedIn: Bool) {
        // here I would like to access the environment variable. Something like
        // userState.loggedIn = loggedIn
    }

}
like image 824
Adriano Avatar asked Jan 01 '20 15:01

Adriano


1 Answers

Here is possible approach...

class AppDelegate: UIResponder, UIApplicationDelegate {
   //creating the variable in AppDelegate to have it shared
   var userState = UserState()
   ...

so, then you can ...

extension AppDelegate {

    func something(loggedIn: Bool) {
        // just use it here as now it is own property
        self.userState.loggedIn = loggedIn
    }
}

and use it in scene delegate via shared application instance

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
   ...

 func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
   // safe as it is known the one AppDelegate
   let appDelegate = UIApplication.shared.delegate as! AppDelegate
   window.rootViewController = UIHostingController(rootView: 
       ContentView().environmentObject(appDelegate.userState))
 }
like image 175
Asperi Avatar answered Sep 30 '22 16:09

Asperi