SwiftUI Completion Logic in View onAppear

66 views Asked by At

I am fairly new to SwiftUI.

In this example I am running a network request through an API that has a completion handler in order to alter the app state, i.e., show a different view based on a tokens (JWT) validity. I am trying to figure out how to use the completion in the .onAppear of my view to do this, any help would be appreciated:

View code

struct LaunchView: View {

let keychainManager = KeychainManager()
let keychainRecords = KeychainRecords()
let tokenManager = TokenManager()

var validSession: Bool

var body: some View {
    ZStack {
        if validSession {
            HomeView()
        } else {
            LoginView()
        }
    }
    .onAppear(){
        do {
            let token = try keychainManager.getToken(identifier: keychainRecords.identifier, service: keychainRecords.service)
            
            let tokenValidationResponse = try tokenManager.validateToken(token: token){ completion in
                if Result<TokenValidationResponse, NetworkError> {
                    guard let message = tokenValidationResponse.Message else { return }
                    
                    if (message == "Success") {
                        validSession = true
                    } else {
                        validSession = false
                    }
                    
                } else {
                    // Show an error message
                    print("Network request failed")
                }
            }
        } catch {
            print(error)
        }
    }
}

Validation code

func validateToken(token: String, completion: @escaping (Result<TokenValidationResponse, NetworkError>) -> Void) {
        
    guard let url = URL(string: BASE_URL + TOKEN) else {
        completion(.failure(.invalidURL))
        return
    }
    
    let body = TokenRequestBody(token: token)
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = try? JSONEncoder().encode(body)
    
    URLSession.shared.dataTask(with: request) { (data, response, error) in
        
        guard let data = data, error == nil else {
            completion(.failure(.noData))
            return
        }
        
        guard let tokenValidationResponse = try? JSONDecoder().decode(TokenValidationResponse.self, from: data) else {
            completion(.failure(.decodingError))
            return
        }
        print(tokenValidationResponse)
        completion(.success(tokenValidationResponse))
        
    }.resume()
}

Thank you (PS I am getting a valid response from the request when printed)

1

There are 1 answers

1
LiLi Kazine On

Mark your variable with @State.

@State var validSession: Bool = false