列表不符合可编码

列表不符合可编码

问题描述:

因此,我正在使用领域,并且两个模型之间具有以下关系:A unit has many tests:

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"

     }
 }

当注释tests属性时,我可以正确地解析该模型的json输出.但是,当我取消注释时,会出现以下错误:

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'

有没有一种方法可以使Codable和Realm变得更好玩?

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

您的代码有几个问题.首先,如果只想实现init(from:)方法,而不是encode方法,则声明符合Decodable而不是Codable.其次,在创建自己的init(from:)方法时需要实现CodingKeys,并且还需要从便捷初始化器中调用类的指定初始化器.

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.

在初始化程序中也不需要else子句,因为tests已经被初始化为空的List,并且向其添加空数组也没有意义.

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)
        }
    }
}