Swift enum Codable со связанными типами - PullRequest
0 голосов
/ 21 января 2019

У меня есть структура с двумя типами, оба перечисления, один из которых с различными ассоциированными значениями в каждом случае перечисления (см. Код).Есть ли обходной путь, чтобы избежать переключения на UDPCommand?Каждый добавленный случай делает переключение длиннее и повторяет код.И нужно снова сделать кодировщик.Я пытаюсь сделать это с помощью дженериков, но не могу заставить это работать.Спасибо

struct UDPMessage {

    let command: UDPCommand
    var data: UDPCommandData

    func jsonString() -> String {
        let encoder = JSONEncoder()
        guard let data = try? encoder.encode(self) else { return "" }
        guard let string = String(data: data, encoding: .utf8) else { return "" }
        return string
    }
}

enum UDPCommand: String, Codable {
    case DISCOVER
    case FILTER
    case TOGGLE
    case SWIPE_CHAT
    case FORWARD
}

enum UDPCommandData {
    case discover(Discover)
    case filter(Filter)
    case toggle(Toggle)
    case swipe(SwipeChat)
    case forwardedMessage(ForwardedMessage)
    case unkkown
}

extension UDPMessage: Codable {

    private enum CodingKeys: String, CodingKey {
        case command, data
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let command = try container.decode(UDPCommand.self, forKey: .command)

        switch command {
        case .DISCOVER:
            let data = try container.decode(Discover.self, forKey: .data)
            self.init(command: command, data: UDPCommandData.discover(data))
        case .FILTER:
            let data = try container.decode(Filter.self, forKey: .data)
            self.init(command: command, data: UDPCommandData.filter(data))
        case .TOGGLE:
            let data = try container.decode(Toggle.self, forKey: .data)
            self.init(command: command, data: UDPCommandData.toggle(data))
        case .SWIPE_CHAT:
            let data = try container.decode(SwipeChat.self, forKey: .data)
            self.init(command: command, data: UDPCommandData.swipe(data))
        default:
            self.init(command: command, data: UDPCommandData.unkkown)
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.command, forKey: .command)
        try self.data.encode(to: encoder)
    }
}
...