简体   繁体   中英

Codable class does not conform to protocol Decodable

Why am I getting a "Type 'Bookmark' does not conform to protocol 'Decodable'" error message?

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
   }

   init(publication: Publication?, indexPath: [Int]) {
      self.publication = publication
      self.indexPath = indexPath
   }
}

I do not wish to save the publication var since the Publication owns the Bookmark but the bookmark needs to know which Publication it belongs to. The decode init of Publication will set the bookmark reference to itself.

The compiler cannot synthesise the required init(from:) method due to the weak reference, so you need to write it yourself.

class Bookmark: Codable {
    weak var publication: Publication?
    var indexPath: [Int]
    var locationInText = 0

    private enum CodingKeys: String, CodingKey {
        case indexPath
        case locationInText
    }

    init(publication: Publication?, indexPath: [Int]) {
        self.publication = publication
        self.indexPath = indexPath
    }

    required init(from decoder:Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        indexPath = try values.decode([Int].self, forKey: .indexPath)
        locationInText = try values.decode(Int.self, forKey: .locationInText)
    }
}

Why am I getting a "Type 'Bookmark' does not conform to protocol 'Decodable'" error message

It's either because Publication isn't Decodable (you have not shown what it is, so it's hard to tell) or because of the weak designation on publication .

Either way, it's easy to fix: you just need to implement init(from:) to complete the implementation of Decodable; the compiler is simply telling you that this implementation cannot be synthesized.

On the hindsight, I received a similar error when trying to set Codable to my class which consisted of NSNumber type variables. See image below:

在此处输入图片说明

Changing NSNumber to primitive data type Int resolved the issue. See below:

在此处输入图片说明

I'm guessing this might be true for other datatypes that require bridging to Swift Standard Library Value Types such as NSString, NSArray and so on

Another reason you could get this message is if your CodingKeys enum isn't exhaustive. If you have three properties in the data type, then your CodingKeys enum needs to have three property/name cases as well.

Simply because your CodingKeys enum is not exhaustive, add publication property to the enum to achieve that.

try this:

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   // All your properties should be included
   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
      case publication   // this one was missing
   }
}

You wont need the init method anymore as the implementation now can be synthesized.

In a similar scenario, I was getting the same issue because the variable name in my CodingKeys was not the same as a class variable. See below

在此处输入图片说明

Any class to be a codeable must have it's all property codeable. Standard library types like String, Int, Double and Foundation types like Date, Data, and UR confirm the codeable protocol but some doesn't.

For eg Note class have all properties of string which confirm codable protocol so no error: 字符串具有可编码的协议,因此类没有错误

But UIImage don't confirm codable protocol so it throw error: Uiimage 没有编码它显示错误

In-short, while implementing Codable, all properties which are non-primitive data type (mean class type or may it can be objective-c class) must be Codable.

   weak var publication: Publication?

in this case publication is of type class so Publication must have implemented Codable

You can omit a property from coding keys enum, only if it has a default value.

From apple docs

Omit properties from the CodingKeys enumeration if they won't be present when decoding instances, or if certain properties shouldn't be included in an encoded representation. A property omitted from CodingKeys needs a default value in order for its containing type to receive automatic conformance to Decodable or Codable.

Bit of a daft one but in case it helps someone else. I got this error because I put enum CodingKeys: CodingKeys instead of enum CodingKeys: CodingKey .

I had a similar issue which I stumbled upon this fix to. As I am new to Swift, I am unsure as to why it works! If anyone knows I would appreciate the knowledge.

I changed this:

let id, type: Int

to this:

let id: Int
let type: Int

I solve this by changing my struct name to current swift file that I want the struct. For example, I want to put this into BookmarkModel.swift , so instead type this:

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
   }

   init(publication: Publication?, indexPath: [Int]) {
      self.publication = publication
      self.indexPath = indexPath
   }
}

Change to this:

class BookmarkModel: Codable {
       weak var publication: Publication?
       var indexPath: [Int]
       var locationInText = 0

       enum CodingKeys: String, CodingKey {
          case indexPath
          case locationInText
       }

       init(publication: Publication?, indexPath: [Int]) {
          self.publication = publication
          self.indexPath = indexPath
       }
    }

If you have tried above all solutions and are still unable to fix the error then I think it could be because of the `data type you are using for your data class fields.

In the question they have used 1 field weak var publication: Publication? , and if you have the same kind of class structure then maybe you should check if that Publication data class conforms to the Codable class or not.

Because it is mandatory to conform same protocol for the child class as well, as tit's fields are also should be encodable and deodable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM