Version 6 (Latest at time of writing)
I'm using this to allow for Codable support (plan to add a PR if I can get this working):
extension Alamofire.DataRequest {
// Return a Promise for a Codable
public func responseCodable<T: Codable>(decoder: JSONDecoder) -> Promise<T> {
return Promise<T> { seal in
responseData(queue: nil) { response in
if let code = response.response?.statusCode {
//custom response code handling
}
switch response.result {
case .success(let value):
do {
seal.fulfill(try decoder.decode(T.self, from: value))
} catch let e {
seal.reject(e)
}
case .failure(let error):
seal.reject(error)
}
}
}
}
}
I'm converting all my Then to Done but I'm getting:
This says: Generic parameter 'T' could not be inferred on the Catch
func updateContactInformation(firstName: String, lastName: String, email: String, completion: @escaping (Bool, Error?) -> Void){
...
Alamofire
.request(urlPath, method: .get, encoding: URLEncoding.default, headers: headers)
.responseCodable(decoder: self.defaultDecoder).done{ user in
self.updateUserCache(user)
completion(user, nil)
}.catch{ error in
print("ERROR updateContactInformation: \(error.localizedDescription)")
completion(nil, error)
}
}
However, commenting out the self.updateUserCache and the print(), so that there's only one like, makes it successfully compile. How can I do both?
If I only remove the print() in the catch, I get this: 'Error' is not convertible to 'Error?'
We already provide Codable support in our Alamofire extension.
Anyway, Swift is trying to figure out T, so to do this it uses your completion parameter, which takes (Bool, Error?), thus it is trying to use Decodable to produce Bool which is impossible.
Sorry, copy/paste error on my part. Also forgot to update pod for AlamofireKit, thanks for that.
I still can't figure it out. The only difference is the complete() function which splits it out. How can I force the T to MYUser codable?
//Working
func getUser(_ userId: String, completion: @escaping (MYUser?, Error?) -> Void) {
func complete(_ user: MYUser){
self.updateUserCache(user)
completion(user, nil)
}
Alamofire
.request(urlPath, method: .get, encoding: URLEncoding.default, headers: headers)
.responseDecodable(decoder: self.defaultDecoder).done{ user in
completion(user, nil)
}.catch{ error in
print("ERROR getUser: \(error.localizedDescription)")
completion(nil, error)
}
}
//Non-Working
func getUser(_ userId: String, completion: @escaping (MYUser?, Error?) -> Void) {
Alamofire
.request(urlPath, method: .get, encoding: URLEncoding.default, headers: headers)
.responseDecodable(decoder: self.defaultDecoder).done{ user in
self.updateUserCache(user)
completion(user, nil)
}.catch{ error in <<< Generic parameter 'T' could not be inferred
print("ERROR getUser: \(error.localizedDescription)")
completion(nil, error)
}
}
Also, removing the print():
}.catch{ error in
completion(nil, error) <<< 'Error' is not convertible to 'Error?'
}
It doesn't work because Swift can only infer types for one line closures.
You can make it work by specifying the type of user in you done.
This is mentioned in the troubleshooting guide.
@mxcl Thanks for the quick replies and your awesome work on this project (and homebrew)!
I'm not following the steps in your mention of Troubleshooting. How do I sepecify the type of user in done?
So I got the above example working by moving it to an internal function handler and reducing it to one line. Now I'm getting the same error for this one:
func loginFacebook(_ accessToken: String, completion: @escaping (Bool, Error?) -> Void){
let urlPath = URL(string: self.endpoint + "rest-auth/facebook/")!
let parameters ...
func complete(){
print("Updating user")
...
completion(true, nil)
}
func completeError(_ error: Error){
completion(false, error)
}
Alamofire
.request(urlPath.absoluteURL, method: .post, parameters: parameters)
.responseCodable(decoder: self.defaultDecoder)
.then { me -> Promise<User> in
print("Setting user copy locally, Signing into Firebase")
self.currentUser = me
return Auth.auth().signIn(withCustomToken: me.firebase_token!)
}.done { _ -> () in
complete()
}.catch{ error in <<<Generic parameter 'T' could not be inferred
completeError(error)
}
}
Before I added completeError() I was getting 'Error' is not convertible to 'Error?'. I can't follow either error and I've tried a lot of different permutations.
How do I sepecify the type of user in done?
}.done { (user: User) in
Thanks @nathanhosselton, @mxcl
Turns out I had to apply that to not-only the .done but the initial .then as well. Perhaps because I've got several subclasses of User.
The initial then was what required it, sorry, we missed the fact in your subsequent example it became a then. Key is that Swift needs to understand the type at that point.
Is this issue resolved? If so please close.
Most helpful comment