如何在类枚举中使用Codable

时间:2018-07-22 04:49:37

标签: swift codable

我觉得对于真正简单的事情我走得太远了。使用以下代码,我得到的错误是:Cannot invoke 'decode' with an argument list of type '(GameOfLife.Cell, forKey: GameOfLife.Cell.CodingKeys)'

extension GameOfLife {
    enum Cell: Equatable, Codable {
        case alive
        case born
        case dying
        case dead

        var isAlive: Bool {
            switch self {
            case .alive, .born: return true
            case .dying, .dead: return false
            }
        }
        var isDead: Bool {
            switch self {
            case .alive, .born: return false
            case .dying, .dead: return true
            }
        }

        func equalTo(_ rhs: Cell) -> Bool {
            switch (self) {
            case .alive, .born:
                return rhs.isAlive
            case .dead, .dying:
                return rhs.isDead
            }
        }

        init(_ living: Bool) {
            self = living ? .alive : .dead
        }

        enum CodingKeys: CodingKey {
            case alive
            case born
            case dying
            case dead
        }

        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            do {
                let leftValue = try container.decode(GameOfLife.Cell.alive, forKey: CodingKeys.alive)
                self = GameOfLife.Cell.alive
            } catch {
                let leftValue = try container.decode(GameOfLife.Cell.born, forKey: CodingKeys.born)
                self = GameOfLife.Cell.born
            } catch {
                let leftValue = try container.decode(GameOfLife.Cell.dying, forKey: CodingKeys.dying)
                self = GameOfLife.Cell.dying
            } catch {
                let leftValue = try container.decode(GameOfLife.Cell.dead, forKey: CodingKeys.dead)
                self = GameOfLife.Cell.dead
            }
        }

        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            switch self {
            case .alive:
                try container.encode("alive", forKey: .alive)
            case .born:
                try container.encode("born", forKey: .born)
            case .dying:
                try container.encode("dying", forKey: .dying)
            case .dead:
                try container.encode("dead", forKey: .dead)
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

decode(的第一个参数是解码对象的预期类型。在对枚举用例进行编码时,String应该是String

let leftValue = try container.decode(String.self, forKey: .alive) // The compiler can infer the type `CodingKeys`

但是整个init(from方法都没有意义。如果catch表达式内发生错误,则不会在随后的catch表达式中捕获错误。

要将枚举大小写编码为String,只需将enum的原始类型声明为String,然后删除CodingKeys以及init(fromencode(to方法。如果要采用Equatable,则必须实现==

extension GameOfLife : Codable {

    enum Cell: String, Equatable, Codable {
        case alive, born, dying, dead

        var isAlive: Bool {
            switch self {
            case .alive, .born: return true
            case .dying, .dead: return false
            }
        }

        // isDead can be simplified
        var isDead: Bool {
            return !isAlive
        }

        static func == (lhs: Cell, rhs: Cell) -> Bool {
           switch (lhs.isAlive, rhs.isAlive) {
             case (true, true), (false, false): return true
             default: return false
           }
       }

        init(_ living: Bool) {
            self = living ? .alive : .dead
        }
    }
}