ios – Best way a specific view in SwiftUI based on the user’s logged in status


My goal is to

  • show a LoginView when the user first launches the app
  • after the user logs in, we should store the token and go to the HomeView
  • any time the user opens the app in the future, we taken user to the HomeView since we have a stored token
  • finally, we should log the user out and return them to the login screen if the token has expired

I tried approaches outlined in this youtube video and this medium article

At a high level, they both talk about injecting some sort of an Authentication object into the environment, something like:

First we have the authentication class which is an observable object

class Authentication: ObservableObject {
    @Published var isValidated = false
    
    func updateValidation(success: Bool) {
        withAnimation {
            isValidated = success
        }
    }
}

We then create the authentication object in the main and pass it to the environment

@main
struct MySecureApp_App: App {
    @StateObject var authentication = Authentication()
    var body: some Scene {
        WindowGroup {
            if authentication.isValidated {
                ContentView()
                    .environmentObject(authentication)
            } else {
                HomeView()
                    .environmentObject(authentication)
            }
        }
    }
}

Then in the login view

struct LoginView: View {
    @StateObject private var loginVM = LoginViewModel()
    @EnvironmentObject var authentication: Authentication

    var body: some View {
            VStack {
                // some login views

                Button("Log in") {
                    loginVM.login { success in
                    authentication.updateValidation(success: success)
                }
            }
        }
    }
}

and then finally in the home view

struct HomeView: View {
    @StateObject private var homeVM = HomeViewModel()
    @EnvironmentObject var authentication: Authentication

    var body: some View {
        NavigationView {
            VStack {
                
            }.onReceive($homeVM.isUnauthorized) // ignore for SwiftUI syntax {
                authentication.updateValidation(success: false)
            }
        }
    }
}

Now while this could work, it seems rather cumbersome to keep passing the authentication object to each and every view.

Is there a way possible that we could inject these StateObjects or environment objects into view models or services ?

In my opinion a good solution might be to set the logout status of the user from the HTTPClient when an API returns an unauthorized response rather than having to check this in every view.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img