Search code examples
firebasefirebase-authenticationswiftuiuiscenedelegate

How do I correct this issue with reading an Environment Object? (SwiftUI and working without a SceneDelegate)


I wanted to write a template for apps that logs into firebase so that I can use it in future projects. I followed a tutorial online found on YouTube : https://www.youtube.com/watch?v=DotGrYBfCuQ&list=PLBn01m5Vbs4B79bOmI3FL_MFxjXVuDrma&index=2

So the issue I'm facing is that in the video the variable userInfo was instantiated in the SceneDelegate, allowing the coder on YouTube to reference userInfo in his code. I tried doing the same in the AppDelegate and the App Struct. with no avail.

Here is the code in the App Struct:

import SwiftUI
import Firebase

@main
struct WoobApp: App {

// Adapts AppDelegate to SwiftUI
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

var userInfo = UserInfo()

var body: some Scene {
    WindowGroup {
        InitialView()
    }
}
}



 class AppDelegate : NSObject, UIApplicationDelegate {

// Configure Firebase When App Launches
func application(_ application : UIApplication, didFinishLaunchingWithOptions launchOptions : [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    
    FirebaseApp.configure()
    return true
}
}

I think the issue is in here, however I will post the rest of my code in case Im wrong:

InitialView:

struct InitialView: View {


@EnvironmentObject var userInfo : UserInfo

var body: some View {
    
    Group {
        if userInfo.isUserAuthenticated == .undefined {
            UndefinedView()
        }
        else if userInfo.isUserAuthenticated == .signedOut {
            UndefinedView()
        }
        else if userInfo.isUserAuthenticated == .signedIn {
            UndefinedView()
        }
    }
    .onAppear{
        self.userInfo.configureFirebaseStateDidChange()
    }
    
    }

And here is the User data :

class UserInfo : ObservableObject {

enum FBAuthState {
    case undefined, signedIn, signedOut
    
}

@Published var isUserAuthenticated : FBAuthState = .undefined

func configureFirebaseStateDidChange() {
    
    isUserAuthenticated = .signedIn
    isUserAuthenticated = .signedOut
    
}
}

Thanks in advance for any help, Id really appreciate it so thank you!!!!


Solution

  • You have to actually pass that userInfo variable into your view hierarchy so that it's visible to InitialView and its children:

    @ObservedObject var userInfo = UserInfo()
    
    var body: some Scene {
        WindowGroup {
            InitialView()
              .environmentObject(userInfo)
        }
    }
    
    

    This principal of passing it via environmentObject is true whether you're using the SwiftUI lifecycle or a SceneDelegate. More reading on environmentObject: https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views

    You have a choice of whether to declare userInfo as an ObservedObject or StateObject that may depend on your OS target version: What is the difference between ObservedObject and StateObject in SwiftUI