How to use Codable protocol for an enum with other enum as associated value (nested enum)

╄→尐↘猪︶ㄣ 提交于 2019-12-11 14:42:32

问题


I asked a question yesterday on how to save a nested enum inside UserDefaults.
I am trying to use the Codable protocol for this, but not sure if I am doing it correctly.

Here is again the enum I want to store -> UserState:

enum UserState {
    case LoggedIn(LoggedInState)
    case LoggedOut(LoggedOutState)
}

enum LoggedInState: String {
    case playing
    case paused
    case stopped
}

enum LoggedOutState: String {
    case Unregistered
    case Registered
}

Here are the steps I did so far:

Conform to Codable protocol and specify which are the keys we use for encode/decode:

extension UserState: Codable {
    enum CodingKeys: String, CodingKey {
        case loggedIn
        case loggedOut
    }

    enum CodingError: Error {
        case decoding(String)       
    }
}

Added initializer for decode:

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    if let loggedIn = try? values.decode(String.self, forKey: .loggedIn) {
        self = .LoggedIn(LoggedInState(rawValue: loggedIn)!)
    }

    if let loggedOut = try? values.decode(String.self, forKey: .loggedOut) {
        self = .LoggedOut(LoggedOutState(rawValue: loggedOut)!)
    }

    throw CodingError.decoding("Decoding failed")
}

Added encode method:

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

    switch self {
    case let .LoggedIn(value):
        try container.encode(value, forKey: .loggedIn) // --> Ambiguous reference to member 'encode(_:forKey:)'
    case let .LoggedOut(value):
        try container.encode(value, forKey: .loggedOut) // --> Ambiguous reference to member 'encode(_:forKey:)'
    }
}

The encode method gives me the above two errors. Not sure right now what I am doing wrong or if I am on the right track.

Any idea what I am doing wrong and what causes these two ambiguous errors ?


回答1:


The associated value is LoggedInState or LoggedOutState but you have to encode its rawValue (String):

    case let .LoggedIn(value):
        try container.encode(value.rawValue, forKey: .loggedIn)
    case let .LoggedOut(value):
        try container.encode(value.rawValue, forKey: .loggedOut)
    }

according to the decode method where you're creating the enum cases from the rawValue.



来源:https://stackoverflow.com/questions/48358141/how-to-use-codable-protocol-for-an-enum-with-other-enum-as-associated-value-nes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!