Home > Net >  error response decoding and passing into alert
error response decoding and passing into alert

Time:10-01

I am creating a simple login app with custom error message display in an alert for API response failure. Below is my code

  @State private var username = ""
  @State private var password = ""
  @State private var isPresentederror = false
var body: some View {
        NavigationView{
            ZStack{
                VStack{
                   
                        
                    TextField("Username", text : $username)
                        .autocapitalization(.none)
                        .padding()
                        .frame(width:300,height: 50)
                        
                    SecureField("Password", text : $password)
                        .padding()
                        .frame(width:300,height: 50)
                        
                    Button("Login"){
                        authenticateUser(username: username, password: password)
                    }
                    
                    .foregroundColor(.white)
                    .frame(width: 300, height: 50)
                    .background(Color.blue)
                    .cornerRadius(10)
                   
                    .alert("Error", isPresented: $isPresentederror, actions: {
                      
                    }, message: {
                        Text("Something went wrong! Please try again")
                    })

                }
            }
            .navigationBarHidden(true)
        }        
    }

on Click of LOGIN button I am calling a function authenticateUser by passing username and password as a parameter Below is my authenticateUser function code

func authenticateUser(username: String, password: String){
      
     
       
        let method = "POST"
        let urlString = "http://myapi_to verify_username_password"
        
        var urlHeader=//header part goes here
        
        let json: [String: Any] = ["password": password,
                                    "username": username]
         let jsonData = try? JSONSerialization.data(withJSONObject: json)
         urlHeader.httpBody = jsonData

        URLSession.shared.dataTask(with: urlHeader) { (data, response , error) in
            
            guard let data = data else { return }
            print(String(data: data, encoding: .utf8) ?? "Invalid JSON")
            do {
                   //success code working fine
               } catch {
                   print("Error:\(error.localizedDescription)")
                   print(error)
                   isPresentederror = true
               }
            }.resume()
        
    }

success is working fine for me, but on error I am showing an alert with manual text "Something went wrong! Please try again". I want to show an error message coming from API. the line

print(String(data: data, encoding: .utf8) ?? "Invalid JSON")

in above function gives an object as below

{"timestamp":"2022-09-30T10:03:29.142 00:00","status":501,"error":"Please verify the data you have sent Found","path":"path_to_url"}

I want to show the error inside alert which is "Please verify the data you have sent Found" coming from API. I tried decoding it and UTF method but it always gives me an error. so please help me to achieve this

CodePudding user response:

You could try this approach, to ...pass response error coming from API, using a @State var errorMessage and testing the httpResponse.statusCode, such as in this example code:

struct LoginView: View {
    @State private var username = ""
    @State private var password = ""
    @State private var isPresentederror = false
    // -- here
    @State var errorMessage = "Something went wrong! Please try again"
    
    var body: some View {
        NavigationView{
            ZStack{
                VStack{
                    TextField("Username", text : $username)
                        .autocapitalization(.none)
                        .padding()
                        .frame(width:300,height: 50)
                    
                    SecureField("Password", text : $password)
                        .padding()
                        .frame(width:300,height: 50)
                    
                    Button("Login"){
                        authenticateUser(username: username, password: password)
                    }
                    .foregroundColor(.white)
                    .frame(width: 300, height: 50)
                    .background(Color.blue)
                    .cornerRadius(10)
                    
                    .alert("Error", isPresented: $isPresentederror, actions: {
                        
                    }, message: {
                        Text(errorMessage) // <-- here
                    })
                    
                }
            }
            .navigationBarHidden(true)
        }
    }
    
    func authenticateUser(username: String, password: String){

        let urlString = "https://myapi_to verify_username_password"
        
        var request = URLRequest(url: URL(string: urlString)!)
        request.httpMethod = "POST"
        
        let json: [String: Any] = ["password": password, "username": username]
        let jsonData = try? JSONSerialization.data(withJSONObject: json)
        request.httpBody = jsonData
        
        URLSession.shared.dataTask(with: request) { (data, response , error) in
            guard let data = data else { return }
            
            print(String(data: data, encoding: .utf8) ?? "Invalid JSON")

            // when the response describing the error, is returned as json
            do {
                let decoded = try JSONDecoder().decode(ApiError.self, from: data)
                errorMessage = decoded.error
                isPresentederror = true
                return
            } catch { }

            // -- here
            guard let httpResponse = response as? HTTPURLResponse else {
                errorMessage = "Unknown error"
                isPresentederror = true
                return
            }
            if (httpResponse.statusCode == 401) {
                errorMessage = "Unauthorized"
                isPresentederror = true
                return
            }
            if (405..<500 ~= httpResponse.statusCode) {
                errorMessage = "Client error"
                isPresentederror = true
                return
            }
            if (500..<600 ~= httpResponse.statusCode) {
                errorMessage = "Server error"
                isPresentederror = true
                return
            }
            // ...etc...
            
            do {
                //success code working fine
                try JSONDecoder().decode([String].self, from: data)
                //....
            } catch {
                print("Error:\(error.localizedDescription)")
                // -- here
                errorMessage = error.localizedDescription
                isPresentederror = true
            }
        }.resume()
    }
    
}

// consult the server docs
struct ApiError: Codable {
    var timestamp: String
    var status: Int
    var error: String
    var path: String
}
  • Related