【发布时间】:2018-07-12 09:31:03
【问题描述】:
我面临一个问题,我无法使 RealmOptional 与带有 json 解码器的 swift 新 Codable 功能兼容。
考虑以下 Realm 对象。
class School: Object, Codable {
@objc dynamic var id: Int64 = 0
@objc dynamic var name: String?
var numberOfStudents = RealmOptional<Int64>()
var classes = List<Class>()
enum CodingKeys: String, CodingKey {
case id
case name
case numberOfStudents
case classes
}
}
class Class: Object, Codable {
var name: String?
var numberOfStudents = RealmOptional<Int64>()
}
在这里我们可以将类声明为 Codable,因为我在 this gist 的帮助下为 RealmOptinal 编写了一个扩展。但问题是解码器解码json的时候。
考虑这个json
let jsonData = """
[
"id": 1234,
"name": "Shreesha",
"numberOfStudents": nil,
"classes": {
"name": "Class V",
"numberOfStudents": 12
}
]
""".data(using: .utf8)!
在这个 json 中,所有的数据都被传递,并且这与代码完美地解码。
let decoder = JSONDecoder()
let decoded = try! decoder.decode(School.self, from: jsonData)
但是,如果我从应该是 RealmOptional 对象的 json 数据中删除 numberOfStudents 键,它将引发错误并且不会解码,因为 RealmOptional 不是快速可选的,因此解码器认为应该有一个键在 json 数据中。在JSONDecoder 中,如果 json 中不存在密钥并且该属性被声明为可选,它不会尝试解码。它只是跳到其他键。
直到现在我还没有重写初始化程序,因为我们拥有RealmOptional Realm Lists 等的所有支持扩展。但是现在我必须重写init(from decoder: Decoder) 来手动解码它,Realm 模型有更多50 个属性(你知道我的意思)。
如果我们覆盖初始化器,我觉得使用 JSONDecoder 没有意义,因为与使用 JSONDecoder 相比,手动工作更多。
required convenience init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(Int64.self, forKey: .id) ?? 0
name = try container.decodeIfPresent(String?.self, forKey: .name) ?? ""
numberOfStudents = try container.decodeIfPresent(RealmOptional<Int64>.self, forKey: .numberOfStudents) ?? RealmOptional<Int64>()
let classesArray = try container.decode([Class].self, forKey: .classes)
classes.append(objectsIn: classesArray)
}
那么有人可以向我建议使 RealmOptional 与JSONDecoder 兼容的替代解决方案,这样我们就不必覆盖初始化程序。
【问题讨论】:
标签: swift realm codable jsondecoder