List is not conforming to Encodable

蹲街弑〆低调 提交于 2019-12-11 07:35:46

问题


So, I'm using realm and I have the following relationship between two models: A unit has many tests:

 // Unit model
 class Unit: Object, Decodable {
     @objc dynamic var id: String = ""
     ...
     let tests = List<Test>()

     enum CodingKeys: String, CodingKey {
          case id
          ...
          //case tests = "complete_control_tests"
     }

     convenience required init(from decoder: Decoder) throws {
          self.init()
          let container = try decoder.container(keyedBy: CodingKeys.self)
          id = try container.decode(String.self, forKey: .id)
          ...
          if let arr = try container.decodeIfPresent(Array<Test>.self, forKey: .tests) {
                tests.append(objectsIn: arr)
          } else {
                self.tests.append(objectsIn: [])
          }
     }
 }
 // Test model
 class Test: Object, Decodable {
     @objc dynamic var id: String = ""
     @objc dynamic var room_control_id: String = ""

     enum CodingKeys: String, CodingKey {
          case id
          case room_control_id = "room_control_id"

     }
 }

When the tests property is commented, I can properly parse the json output for that model. But then when I uncommented it, I have the following errors:

Swift.Encodable:12:17: Protocol requires function 'encode(to:)' with type 'Encodable'
Models/Unit.swift:27:6: Cannot automatically synthesize 'Encodable' because 'List<Test>' does not conform to 'Encodable'

Is there a way to make Codable and Realm play nice?


回答1:


There are several issues with your code. First of all, if you only want to implement the init(from:) method, but not the encode method, declare conformance to Decodable rather than Codable. Secondly, you need to implement CodingKeys when creating your own init(from:) method and you also need to call a designated initializer of your class from a convenience initializer.

There's also no need for the else clause in the initializer, since tests is initialized as an empty List already and appending an empty array to it makes no sense.

class Unit: Object, Decodable {
    @objc dynamic var id: String = ""
    let tests = List<Test>()

    private enum CodingKeys: String, CodingKey {
        case id, tests
    }

    convenience required init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(String.self, forKey: .id)
        if let arr = try container.decodeIfPresent(Array<Test>.self, forKey: .tests) {
            tests.append(objectsIn: arr)
        }
    }
}



回答2:


The first error message clearly states that if you implement custom init method (decode) you have also to implement encode(to:) (encode) to conform to the protocol.

If you are only decoding the object and you don't need to encode it adopt only Decodable. Otherwise implement encode(to:).

To solve the second error declare the CodingKeys explicitly.




回答3:


I've found why it's not working. It was Xcode's cache. I've deleted the contents of Xcode Derived data folder and now it's compiling and parsing the json correctly.

Sorry, folks !



来源:https://stackoverflow.com/questions/48619049/list-is-not-conforming-to-encodable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!