我使用泛型编写了一个方法,以使其可重复用于任何类型的下载。它下载 json 数组并返回一个通用对象或一个错误。 这是我从服务器下载 json 数组的类:
import Foundation
enum Result<T> {
case success(T)
case failure(Error)
}
class LTLNetworkClient: NSObject {
fileprivate var session : URLSession
fileprivate var objectTask : URLSessionDataTask?
override init() {
let config = URLSessionConfiguration.ephemeral
config.timeoutIntervalForResource = 5
config.timeoutIntervalForRequest = 5
self.session = URLSession.init(configuration: config)
}
/**
Download asynchronously json object from Server and returns it into generic data models
*/
func getData<K: Codable>(request: URLRequest, completion: @escaping (Result<[K]>) -> Void) {
let sessionDataTask = URLSession.shared.dataTask(with: request) { (responseData, response, responseError) in
if let jsonData = responseData {
let decoder = JSONDecoder()
do {
let response = try decoder.decode([K].self, from: jsonData)
let result: Result<[K]> = Result.success(response)
completion(result)
} catch {
completion(.failure(error))
}
} else if let error = responseError {
completion(.failure(error))
} else {
let error = NSError(domain: "Cannot form jsonData with Response Data", code: 501, userInfo: nil)
completion(.failure(error))
}
}
sessionDataTask.resume()
}
}
这就是我调用该方法的方式和我得到的错误:
有谁知道如何修复它以及为什么会出现此错误? 提前多谢
最佳答案
这是您的方法声明:
func getData<K: Codable>(request: URLRequest, completion: @escaping (Result<[K]>) -> Void)
这个方法有一个类型参数,K
, 仅用于 completion
的类型争论。当编译器看到对 getData
的调用时, 它必须为 K
推导出具体类型基于你作为 completion
传递的闭包的参数类型.
这是你的电话:
networkClient.getData(request: urlRequest) { (result) in // Do stuff }
在此调用中,completion
关闭是 { (result) in }
. result
的类型是什么?没有关于它的信息,所以编译器只知道 result
必须输入 Result<[K]>
对于某些类型 K
.它无法推断出 K
的具体类型, 所以它会发出错误。
您可以像这样显式显示类型:
networkClient.getData(request: urlRequest) { (_ result: Result<[SomeConcreteCodableType]>) -> Void in
// Do stuff
}
哪里SomeConcreteCodableType
是一些符合 Codable
的具体类型. Codable
由于 getData
中的约束,需要一致性的声明。
另一种解决方案是更改 getData
采用另一个参数让调用者指定 K
直接:
func getArray<K: Codable>(of: K.Type, for request: URLRequest,
completion: @escaping (Result<[K]>) -> Void) {
...
}
然后你这样调用它:
networkClient.getArray(of: SomeConcreteCodableType.self, for: request) { result in
// Do stuff
}
关于swift - 使用泛型下载的方法需要更多上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56382676/