Implementing Redirect to Login Screen on Token Expiry or Error Occurrence in SwiftUI for iOS and macOS Development with Swift

Implementing Redirect to Login Screen on Token Expiry or Error Occurrence in SwiftUI

In this article, we will explore how to redirect a user to the login screen when their session token expires or an error occurs while making an API call using SwiftUI. We will delve into the details of the SessionManager class, the APINetwork singleton class, and the ContentView that uses them.

Understanding the Session Manager Class

The SessionManager class is responsible for managing the user’s session state. It has two possible states: .loggedIn or .loggedOut. The class inherits from ObservableObject, which allows it to notify its parent views when the state changes.

class SessionManager: ObservableObject {
    enum CurrentState {
        case loggedIn
        case loggedOut
    }

    @Published private(set) var currentState: CurrentState?

    init() {
        let userInfo = UserInfo.shared.getCurrentUserDetails()
        if (userInfo?.authToken ?? "") != "" {
            currentState = .loggedIn
        } else {
            currentState = .loggedOut
        }
    }

    func signIn() {
        currentState = .loggedIn
    }

    func signOut() {
        UserInfo.shared.removeUserInfo()
        currentState = .loggedOut
    }
}

Understanding the APINetwork Singleton Class

The APINetwork singleton class is responsible for making API calls to retrieve data. It has two methods: postAPICall and getAPICall. The postAPICall method sends a POST request to the specified URL with the provided parameters, while the getAPICall method sends a GET request to the specified URL.

class APINetwork {
    static let shared = APINetwork()
    @EnvironmentObject var session: SessionManager

    func postAPICall<T:Codable>(
        url: String,
        param: [String: Any],
        expecting: T.Type,
        completion: @escaping (Result<T, Error>) -> Void) {
        // ...
    }

    func getAPICall<T:Codable>(
        urlString: String,
        inpParam: Any?,
        expecting: T.Type,
        passToken: Bool = true,
        completion: @escaping (Result<T, Error>) -> Void
    ) {
        // ...
    }
}

Understanding the ContentView

The ContentView is the main view of the app. It uses the SessionManager class to determine whether the user is logged in or not. If the user is logged in, it displays the HomeView; otherwise, it displays the LoginView.

struct ContentView: View {
    @EnvironmentObject var session: SessionManager

    var body: some View {
        if session.currentState == .loggedIn {
            HomeView()
        } else {
            LoginView()
        }
    }
}

Implementing Redirect to Login Screen

To redirect the user to the login screen when their session token expires or an error occurs, we need to modify the APINetwork class. Specifically, we want to call the signOut method of the SessionManager class when the API request fails with a 500 status code.

class APINetwork {
    // ...

    func getAPICall<T:Codable>(
        urlString: String,
        inpParam: Any?,
        expecting: T.Type,
        passToken: Bool = true,
        completion: @escaping (Result<T, Error>) -> Void
    ) {
        // ...

        if let httpResponse = response as? HTTPURLResponse {
            switch httpResponse.statusCode {
            case 500:
                self.session.signOut()
                print("Error occurred")
            default:
                print("Default status code")
            }
        }

        // ...
    }
}

Conclusion

In this article, we have explored how to redirect a user to the login screen when their session token expires or an error occurs while making an API call using SwiftUI. We have delved into the details of the SessionManager class, the APINetwork singleton class, and the ContentView that uses them. By modifying the APINetwork class, we can implement a redirect to the login screen when errors occur.

Example Use Case

Here is an example use case for this implementation:

@main
struct SwiftUIIPMSApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(SessionManager())
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var session: SessionManager

    var body: some View {
        if session.currentState == .loggedIn {
            HomeView()
        } else {
            LoginView()
                .environmentObject(session)
        }
    }
}

In this example, the ContentView uses the SessionManager class to determine whether the user is logged in or not. If the user is logged in, it displays the HomeView; otherwise, it displays the LoginView. When an error occurs while making an API call, the APINetwork class redirects the user to the login screen by calling the signOut method of the SessionManager class.

Note that this implementation assumes that you have already set up a SessionManager class and an APINetwork singleton class. The code provided in this example is meant to demonstrate how to implement redirect to the login screen when errors occur, but it may need to be modified to fit your specific use case.


Last modified on 2024-10-29