Swift 4 Использование обобщений в качестве возвращаемого значения - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть такой протокол:

protocol ModelProtocol{

    func parse<T.Model>(data: Data) -> Array<T>? {}

}

Возвращаемое значение представляет собой массив значений параметров. Метод принимает данные, анализирует их и возвращает массив проанализированных объектов из данных API.

Тип данных, которые возвращает API, называется MyData, для которого в качестве значения словаря используется массив.

Я анализирую JSON вот так

func parse<T>(data: Data) -> Array<T>? {
    do {

        let newJSONDecoder = JSONDecoder()
        let menu = try newJSONDecoder.decode(MyData.self, from:data)
        let dataArray = menu.data //array
        let modelArray = Array<T>()
        for object in dataArray {


            modelArray.append(object)

        }

        return modelArray

    }
    catch {
        print("error while parsing:\(error.localizedDescription)")
        return nil
    }

}

Я получаю сообщение об ошибке в строке, в которую добавляюсь в возвращаемый массив.

Невозможно вызвать 'append' со списком аргументов типа '(MyData.Drinks)'

В конечном итоге я хочу, чтобы в возвращаемом массиве были объекты типа, который находится в массиве MyData.data - в данном случае типом является Drinks. Но в более широком смысле я хочу, чтобы метод возвращал любой тип из любой полезной нагрузки JSON. Цель состоит в том, чтобы создать метод, который может принимать любые данные и возвращать любой объект как проанализированный объект типа X в массиве.

Как мне это сделать?

1 Ответ

0 голосов
/ 10 сентября 2018

Прежде всего код не компилируется:

Методы протокола не должны иметь тела

так что вы должны удалить скобки:

protocol ModelProtocol{
    func parse<T : Decodable>(data: Data) -> Array<T>?
}

Для решения вашей проблемы создайте MyData также как универсальный

struct MyData<T : Decodable> : Decodable {
    let data : [T]?
}

и объявить parse

func parse<T : Decodable>(data: Data) -> Array<T>? {

    do {
        let newJSONDecoder = JSONDecoder()
        let menu = try newJSONDecoder.decode(MyData<T>.self, from:data)
        return menu.data
    }
    catch {
        print("error while parsing: ", error)
        return nil
    }
}

print всегда всего error, чтобы получить подробную информацию об ошибке декодирования. localizedDescription слишком широкий.


Если ожидается, что data будет необязательным, то сделайте parse throw и передайте ошибку декодирования

protocol ModelProtocol{
    func parse<T : Decodable>(data: Data) throws -> Array<T>
}

struct MyData<T : Decodable> : Decodable {
    let data : [T]
}

func parse<T : Decodable>(data: Data) throws -> Array<T> {
    let newJSONDecoder = JSONDecoder()
    let menu = try newJSONDecoder.decode(MyData<T>.self, from:data)
    return menu.data
}
...