How to make protocol as codable?

I am getting this wierd error as : Bird doesnot conform to protocol codable.How can i fix this?





protocol Flyable: Codable {
    var type: String { get }
    var value: String { get }
}
struct Bird: Codable {
    let canFly: [Flyable]
    let name: String
}
Post not yet marked as solved Up vote post of gurungbishow Down vote post of gurungbishow
8.9k views

Replies

Look in the Issues navigator (Command-5). There are error messages about the missing "encode" and "init" methods, but there is also a note message;


note: cannot automatically synthesize 'Encodable' because '[Flyable]' does not conform to 'Encodable'


This looks like a bug. If I write out the code that's supposed to be synthesized:


protocol Flyable: Codable {
  var type: String { get }
  var value: String { get }
}
struct Bird: Codable {
  let canFly: [Flyable]
  let name: String

  enum CodeKeys: CodingKey
  {
       case canFly
       case name
  }

  init(from decoder: Decoder) throws {
       let container = try decoder.container(keyedBy: CodeKeys.self)
       canFly = try container.decode ([Flyable].self, forKey: .canFly)
       name = try container.decode (String.self, forKey: .name)
  }

  func encode(to encoder: Encoder) throws
  {
       var container = encoder.container(keyedBy: CodeKeys.self)
       try container.encode (canFly, forKey: .canFly)
       try container.encode (name, forKey: .name)
  }
}


there are no errors (in a playground), and clearly "canFly" is Encodable in line 24.

Did I miss something on protocols ? I thought (reading Swift Programming language / Protocols / Property requirements) that we need to declare the properties in the struct, such as :


protocol Flyable: Codable {
    var type: String { get }
    var value: String { get }
}
struct Bird: Codable {
    var type: String
    var value: String

    let canFly: [Flyable]
    let name: String
}


Am I wrong ?

Edited: Yes, Bird conforms to Codable, not Flyable. Sorry for the mistake.

How can you init the Bird,i cant find the default initializer.

A default initializer will not be synthesized when there is an explicit initializer. You could add the following to Bird:


init(canFly: [Flyable], name: String) {
    self.canFly = canFly
    self.name = name
}

Yes, but this crashes while using encode function.

The funny thing is, that this doesn't work when `canFly` is of type `Flyable` instead of `[Flyable]`