Swift 4 с использованием обобщений в качестве возвращаемого значения

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

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
    }

}

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

Cannot invoke 'append' with an argument list of type '(MyData.Drinks)'

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

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

Непонятно, что переменная MyData и тип MyData имеют одно и то же имя. Далее общий тип должен должен быть ограничен до Decodable..

vadian 10.09.2018 11:25

Хорошо, я могу изменить имя переменной, но проблема все еще сохраняется.

noobsmcgoobs 10.09.2018 11:32

Вы должны обновить свой вопрос, включив минимальный воспроизводимый пример. Объявление вашего протокола некорректно, оно даже не компилируется. Кроме того, вы должны включить декларацию MyData.

Dávid Pásztor 10.09.2018 11:52
0
3
1 205
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, код не компилируется:

Protocol methods must not have bodies

поэтому вам придется снять скобки:

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 будет необязательным, сделайте parsethrow и передайте ошибку декодирования

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
}

Другие вопросы по теме