I have code that calls an API to authenticate a user. The code is shown below:
guard let url = URL(string: "https://somewebsiteapiurl/login") else {
completion(.failure(NetworkError.badURL))
return
}
let body = LoginRequestBody(username: username, password: password)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONEncoder().encode(body)
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
completion(.failure(NetworkError.noData))
return
}
guard let loginResponse = try? JSONDecoder().decode(LoginResponse.self, from: data) else {
completion(.failure(NetworkError.decodingError))
return
}
guard let token = loginResponse.token else {
completion(.failure(AuthenticationError.invalidCredentials))
return
}
completion(.success(token))
}.resume()
}
Depending on the type of error I call the .failure with the respective Error case.
enum NetworkError: Error {
case badURL
case noData
case decodingError
}
enum AuthenticationError: Error {
case invalidCredentials
}
My first question is that is this a good way to do it. And also how would I handle these cases on the client side since sometimes the error comes from NetworkError enum and other times it is AuthenticationError.