How do I make an enum Decodable in swift 4?

前端 未结 8 676
死守一世寂寞
死守一世寂寞 2020-11-28 20:16
enum PostType: Decodable {

    init(from decoder: Decoder) throws {

        // What do i put here?
    }

    case Image
    enum CodingKeys: String, CodingKey {
          


        
8条回答
  •  迷失自我
    2020-11-28 21:14

    To extend on @Toka's answer, you may too add a raw representable value to the enum, and use the default optional constructor to build the enum without a switch:

    enum MediaType: String, Decodable {
      case audio = "AUDIO"
      case multipleChoice = "MULTIPLE_CHOICES"
      case other
    
      init(from decoder: Decoder) throws {
        let label = try decoder.singleValueContainer().decode(String.self)
        self = MediaType(rawValue: label) ?? .other
      }
    }
    

    It may be extended using a custom protocol that allows to refactor the constructor:

    protocol EnumDecodable: RawRepresentable, Decodable {
      static var defaultDecoderValue: Self { get }
    }
    
    extension EnumDecodable where RawValue: Decodable {
      init(from decoder: Decoder) throws {
        let value = try decoder.singleValueContainer().decode(RawValue.self)
        self = Self(rawValue: value) ?? Self.defaultDecoderValue
      }
    }
    
    enum MediaType: String, EnumDecodable {
      static let defaultDecoderValue: MediaType = .other
    
      case audio = "AUDIO"
      case multipleChoices = "MULTIPLE_CHOICES"
      case other
    }
    

    It can also be easily extended for throwing an error if an invalid enum value was specified, rather than defaulting on a value. Gist with this change is available here: https://gist.github.com/stephanecopin/4283175fabf6f0cdaf87fef2a00c8128.
    The code was compiled and tested using Swift 4.1/Xcode 9.3.

提交回复
热议问题