Reputation: 69
I have an API call which checks for the UserLogin and Password and sends a response based on whether the username and password Pairs are correct or not.
The API returns a dictionary if the username-password pair is incorrect and an array of dictionaries if the username-password is correct.
The problem I face is that I am unable to downcast the response from Alamofire to a particular data type.
func afLoginDriver(firstName: String,password:String,completion: @escaping ([Dictionary<String, Any>])->Void){
let driverLoginURL = "URL here.."
let parameters = ["firstName" : firstName, "Password" : password]
AF.request(driverLoginURL, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
switch response.result {
case .success:
let driverLoginResponse = response.value as? [Dictionary<String, Any>]
completion(driverLoginResponse)
break
case .failure(let error):
print(error)
}
}
}
The variable driverLoginResponse throws up an error if the username-password pairs is incorrect as it is only a dictionary and not an array of dictionary.
I tried using the guard let statement but still was not able to get this to work.
Upvotes: 1
Views: 946
Reputation: 119224
I would use Codable
and enum
for that but consider this:
First, implement an enum
with any possible response:
enum LoginDriverResponseValue {
case dictionary([String: Any])
case array([[String: Any]])
case string(String)
case unknown(Any)
}
then, change the function signature to adapt with that enum:
func afLoginDriver(firstName: String, password: String, completion: @escaping (LoginDriverResponseValue)->Void) {
,,,
}
And lastly, switch on the enum and call corresponding completion:
guard let responseValue = response.value else { return }
switch responseValue {
case let result as [String: Any]: completion(.dictionary(result))
case let result as [[String: Any]]: completion(.array(result))
case let result as String: completion(.string(result))
default: completion(.unknown(responseValue))
}
you can encapsulate responseValue
type detection into the enum LoginDriverResponseValue
:
extension LoginDriverResponseValue {
init(responseValue: Any) {
switch responseValue {
case let result as [String: Any]: self = .dictionary(result)
case let result as [[String: Any]]: self = .array(result)
case let result as String: self = .string(result)
default: self = .unknown(responseValue)
}
}
}
So then the only thing you need in the function will be:
guard let responseValue = response.value else { return }
completion(LoginDriverResponseValue(responseValue: responseValue))
Upvotes: 2
Reputation: 434
if let responseOne = response.value as? [String: Any] {
// ...
} else if let responseTwo = response.value as? [[String: Any]] {
// ...
}
struct Response: Codable {
var valueOne: [String: Any]?
var valueTwo: [[String: Any]]?
}
Upvotes: 3