Swift 4:向下转换回调函数问题



我有一个用于服务器端连接的 API 类:

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)
}
}

我的应用程序中的每个响应都继承自 CodablityResponse 协议,该协议继承自 Codabilty 协议:

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 { }

我常见的补全函数看起来像:

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
}
}

问题出在这一行self.commonCompletion(response: response, for: completion),尽管LoginResponse继承自CodabilityResponse,但它不能从(LoginResponse)->Void下降到(CodabilityResponse)-> Void如果我添加强制铸造,则会出现下一个错误:Generic parameter 'T' could not be inferred

我打破了我的头,我不知道出了什么问题。 有什么建议吗?

尽管LoginResponse类型继承自CodabilityResponse,因此您可以在指定后者的地方返回前者的实例,但问题出在完成处理程序的类型上。

完成处理程序的类型是(CodabilityResponse)-> Void,不能从不相关的类型向下转换(LoginResponse) -> Void

而不是

static func login(loginData: LoginRequest, completion: @escaping (LoginResponse) -> Void)

static func login(loginData: LoginRequest, completion: @escaping CompletionHandler)

这样completion的类型是正确的,由于LoginResponse继承自CodabilityResponse,因此您可以将它的实例传递给commonCompletion

最新更新