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.
Codable is Encodable , but the compiler says it does not conform to it. This may sound strange, but it's because we are using Codable as a type, and the type Codable (not the protocol definition of Codable ) does not conform to Encodable .
If all the properties of a type already conform to Codable , then the type itself can conform to Codable with no extra work – Swift will synthesize the code required to archive and unarchive your type as needed.
Understanding what Swift's Codable isWhen you only want to convert JSON data into a struct, you can conform your object to Decodable . If you only want to transform instances of your struct into Data , you can conform your object to Encodable , and if you want to do both you can conform to Codable .
Codable is the combined protocol of Swift's Decodable and Encodable protocols. Together they provide standard methods of decoding data for custom types and encoding data to be saved or transferred.
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) } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With