Reputation: 1504
I have an API class for server side connection:
class APIClient {
typealias CompletionHandler = (CodabilityResponse) -> Void
@discardableResult
private static func performRequest<T:Decodable>(route: APIRouter, completion: @escaping (T) -> Void) -> DataRequest {
return Alamofire.request(route).responseJSON(completionHandler: { (response) in
do {
//print("The response is: \(response.result.value)")
let json = try JSONDecoder().decode(T.self, from: response.data!)
completion(json)
} catch let err {
print("Err", err)
}
})
}
static func login(loginData: LoginRequest, completion: @escaping (LoginResponse) -> Void) {
performRequest(route: APIRouter.login(loginData: loginData)) { (response) in
self.commonCompletion(response: response, for: completion)
}
}
Each response in my application inherit from CodablityResponse protocol, which inherit from Codabilty protocol:
protocol Codability: Codable { }
extension Codability {
typealias T = Self
func encode() -> Data? {
return try? JSONEncoder().encode(self)
}
static func decode(data: Data) -> T? {
return try? JSONDecoder().decode(T.self, from: data)
}
}
protocol CodabilityResponse: Codability {
var status: String { get }
var errorMessage: [String]? { get }
var errorCode: Int { get }
}
extension CodabilityResponse { }
My common completion function is looks like:
private static func commonCompletion(response: CodabilityResponse, for commonCompletion: @escaping CompletionHandler) {
if response.status == APIStatus.success.rawValue && response.errorCode == APIErrors.OK.rawValue {
commonCompletion(response)
}
else {
//TODO SHOW ERROR ONLY IN THIS PLACE
}
}
The problem is in this row self.commonCompletion(response: response, for: completion)
, it can not downcast from (LoginResponse)->Void
to (CodabilityResponse)-> Void
in spite the fact that LoginResponse
inherits from CodabilityResponse
If I add force casting then I get next error: Generic parameter 'T' could not be inferred
I broke my head my have no idea what is wrong. Any suggestions?
Upvotes: 0
Views: 348
Reputation: 114975
Although the type LoginResponse
inherits from CodabilityResponse
and you can therefore return an instance of the former where the latter is specified, it is the type of the completion handler that is the issue.
The type of the completion handler is (CodabilityResponse)-> Void
which can't be downcast from the unrelated type (LoginResponse) -> Void
Instead of
static func login(loginData: LoginRequest, completion: @escaping (LoginResponse) -> Void)
Use
static func login(loginData: LoginRequest, completion: @escaping CompletionHandler)
That way completion
is of the correct type and since LoginResponse
inherits from CodabilityResponse
you can pass an instance of it to commonCompletion
Upvotes: 1