Swift 4 кодирует вложенное перечисление возвращается пустым - PullRequest
0 голосов
/ 07 июня 2018

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

Атрибутами могут быть либо идентификаторы, либо объекты

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

Пример:

"platforms": [
    6
]

"platforms": [
    {
        "id": 6,
        "name": "PC (Microsoft Windows)",
        "slug": "win",
        "url": "https://www.igdb.com/platforms/win",
        "created_at": 1297639288000,
        "updated_at": 1470063140518,
        "website": "http://windows.microsoft.com/",
        "alternative_name": "mswin"
    }
]

Я создал косвенное перечисление ObjectType для обработки этого

extension ObjectType{
    enum CodingError: Error {
        case decoding(String)
    }
    enum CodableKeys: String, CodingKey {
        case Struct, Id
    }
}

/**
    ObjectType keeps track of struct expansion with two different 'states'
    Struct OR Int64
    If the request is expanded then the ObjectType will be a struct of that type. Otherwise it will be the id

    @param T the struct type it should expand to, if expanded.
*/
public indirect enum ObjectType<T: Codable>: Codable {
    case Struct(T)
    case Id(Int64)

    // decodes the response to the correct 'state', Struct or Int64.
    public init(from decoder: Decoder) throws {
        let values = try decoder.singleValueContainer()

        if let standardID = try? values.decode(Int64.self) {
            self = .Id(standardID)
        } else if let extendedID = try? values.decode(T.self) {
            self = .Struct(extendedID)
        } else {
            throw CodingError.decoding("Decoding Failed \(dump(values))")
        }
    }

    // encodes the response to the correct 'state', Struct or Int64.
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodableKeys.self)

        switch self {
        case let .Struct(extendedID):
            /* this line is weird */
            try container.encode(extendedID, forKey: .Struct)

        case let .Id(standardID):
            try container.encode(standardID, forKey: .Id)
        }
    }

Это прекрасно работает для декодирования, но не работает для кодированияstructs.

Отладка строки "try container.encode (extendedID, forKey: .Struct)" в Xcode для случая .Struct возвращает "(())", пустая структура.

Iне понимаю, почему кодировщик возвращает пустое значение, что я делаю не так?

1 Ответ

0 голосов
/ 08 июня 2018

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

Я неправильно использовал кодировщик.Это мой старый код:

public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodableKeys.self)

    switch self {
    case let .Struct(extendedID):
        /* this line is weird */
        try container.encode(extendedID, forKey: .Struct)

    case let .Id(standardID):
        try container.encode(standardID, forKey: .Id)
    }
}

Это рабочий код:

public func encode(to encoder: Encoder) throws {
/* var container = encoder.container(keyedBy: CodableKeys.self) */

    switch self {
    case let .Struct(extendedID):
        try extendedID.encode(to: encoder)
     /* try container.encode(extendedID, forKey: .Struct) */

    case let .Id(standardID):
        try standardID.encode(to: encoder)
     /* try container.encode(standardID, forKey: .Id) */
    }
}

Решение выглядит очень похоже, но я до сих пор не понимаю, почему это работает, а не мой предыдущийрешение.

...