快速传递json解码类型到http请求

时间:2019-02-03 14:45:49

标签: json swift

我想制作一个静态函数,该函数可以返回如下所示的结构:

struct Category: Codable {
    public let data: Array<CateItem>
    public let status: Int
    public let msg: String
}

我已经写了一个像这样的静态函数:

static func Get(codePoint: String, responseType: Codable){
    let urlString = UrlUtils.GetUrl(codePoint: codePoint)
    let url = URL(string: urlString)
    let task = URLSession.shared.dataTask(with: url!){
        (data,response,error) in
        if error != nil{
            print(error!)
        }else{
            if let data = data{
                JSONDecoder().decode(responseType, from: data)
            }
        }
    }
    task.resume()
}

并调用如下方法:

HttpRequests.Get(codePoint: "getCategoryList", responseType:  Category)

但是这里responseType无效。

该如何解决?

1 个答案:

答案 0 :(得分:4)

您要传递结构类型,而不是协议。

首先,对方法进行一般约束,即说T必须符合Decodable(由于仅用于解码就需要它,因此不需要符合Encodable

然后说参数应该为T.Type类型-这允许编译器推断类型为T,您可以避免使用此参数,请参见回答

static func Get<T: Decodable>(codePoint: String, responseType: T.Type) { ... }

...因此T将是您将传递给方法的类型。


然后,JSONDecoder的{​​{1}}方法使用的类型为decode

T

,然后当您要调用方法时,像在解码中一样传递结构的类型

JSONDecoder().decode(T.self, from: data)

还要注意,您的调用是异步的,因此要返回数据,您需要将补全处理程序定义为方法的参数

HttpRequests.Get(codePoint: "getCategoryList", responseType: Category.self)

请注意,方法名称应以小写大写字母开头

completion: @escaping (T?) -> Void

static func get<T: Decodable>(codePoint: String, responseType: T.Type, completion: @escaping (T?) -> Void) {

    let urlString = UrlUtils.GetUrl(codePoint: codePoint)
    let url = URL(string: urlString)

    URLSession.shared.dataTask(with: url!) { data, response, error in

        guard let data = data else {
            print(error!)
            return completion(nil)
        }

        do {
            let decoded = try JSONDecoder().decode(T.self, from: data)
            completion(decoded)
        } catch {
            print(error)
            completion(nil)
        }
    }.resume()
}

您还可以避免使用HttpRequests.get(codePoint: "getCategoryList", responseType: Category.self) { response in if let category = response { ... } } 参数,因为responseType的类型可以从完成闭包的参数类型中推断出来

T

static func get<T: Codable>(codePoint: String, completion: @escaping (T?) -> Void) { ... }