使用泛型下载的方法需要更多上下文

时间:2019-05-30 17:08:54

标签: swift generics nsurlsession

我使用泛型编写了一种方法,以使其可重用于任何类型的下载。它下载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()
    }
}

这就是我调用方法和得到的错误的方式:

enter image description here

有人知道如何解决它,为什么会出现此错误? 提前很多

1 个答案:

答案 0 :(得分:2)

这是您的方法声明:

scale_x_continuous

此方法具有类型参数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 }是什么类型?没有给出任何相关信息,因此编译器只知道对于某些类型resultresult必须是类型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) {
    ...
}