Тип быстрого декодирования json в http запрос - PullRequest
0 голосов
/ 03 февраля 2019

Я хочу создать статический функционал, который мог бы возвращать определенную структуру следующим образом:

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 голосов
/ 03 февраля 2019

Вы хотите передать тип структуры, а не протокол.

Сначала создайте общее ограничение для вашего метода, который говорит, что T должен соответствовать Decodable (поскольку он нужен только для декодирования,вам не нужно соответствовать Encodable)

Затем скажите, что параметр должен иметь тип T.Type - это позволяет компилятору выводить тип T, вы можете избежать использованияэтот параметр см. в конце ответа

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

... так что T будет типом, который вы передадите методу.


Тогда для JSONDecoder 'decode метод использует тип T

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

, а затем, когда вы хотите вызвать свой метод, передайте тип вашей структуры, как вы это делали в декодировании

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

Также обратите внимание, что ваш вызов асинхронный, поэтому для возврата данных вам понадобится обработчик завершения , определенный как параметр вашего метода

completion: @escaping (T?) -> Void

noteчто имена методов должны начинаться с маленьких заглавных букв

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

Вы можетеn также избегайте использования параметра responseType, поскольку тип T может быть выведен из типа параметра закрытия завершения

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

HttpRequests.get(codePoint: "getCategoryList") { (category: Category?) -> Void in ... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...