Search code examples
swiftprotocolscodableencodable

Type needs to conform to Encodable protocol even though it is already


Error:

Instance method 'encodeIfPresent(_:forKey:)' requires that '[RelatedQuestions].Type' conform to 'Encodable'

The object i have already conforms to the Codable protocol and it is still giving me the error that it is not. Why?

func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(date, forKey: .date)
        try container.encode(imgURL, forKey: .imgURL)
        try container.encode(thumbnail, forKey: .thumbnail)
        try container.encode(title, forKey: .title)
        try container.encodeIfPresent(tweetText, forKey: .tweetText)
        try container.encode(content, forKey: .content)

        try container.encode(isDailyHidden, forKey: .isDailyHidden)
        try container.encodeIfPresent([Wisdom], forKey: .wisdom) //ERROR
        try container.encodeIfPresent(churchFather, forKey: .churchFather)
        try container.encodeIfPresent(popeSay, forKey: .popeSay)
        try container.encodeIfPresent([RelatedQuestions], forKey: .relatedIds) //ERROR
        try container.encodeIfPresent([Video], forKey: .video) // ERROR
}

Here is one of the models that conforms to Codable.

struct RelatedQuestions: Codable {
    let id: String
    let number, title, imgUrl, thumbnail: String

    enum CodingKeys: String, CodingKey {
        case id, number, title, thumbnail
        case imgUrl = "img_url"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        title = try container.decode(String.self, forKey: .title)
        number = try container.decode(String.self, forKey: .number)
        imgUrl = try container.decode(String.self, forKey: .imgUrl)
        id = try container.decode(String.self, forKey: .id)
        thumbnail = try container.decode(String.self, forKey: .thumbnail)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(title, forKey: .title)
        try container.encode(number, forKey: .number)
        try container.encode(imgUrl, forKey: .imgUrl)
        try container.encode(thumbnail, forKey: .thumbnail)

    }
}

I cleaned the build folder restarted Xcode. Same issue. What have i done wrong??


Solution

  • Oh, I see. This is an obvious typo on your side.

    [RelatedQuestions] is a type. It's not something to encode. You have to use the actual local variable, e.g. self.relatedQuestions.

    Also note that your decoding and encoding functions are fairly simple and can be generated automatically, e.g. :

    struct RelatedQuestions: Codable {
       let id: String
       let number, title, imgUrl, thumbnail: String
    
       private enum CodingKeys: String, CodingKey {
          case id, number, title, thumbnail
          case imgUrl = "img_url"
       }
    }
    

    Actually, even the CodingKeys could be generated automatically.