Swift   发布时间:2022-04-29  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何使RealmSwift RealmOptional与Swift Codable兼容?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我面临一个问题,我无法通过json解码器使RealmOptional与 swift新的Codable功能兼容.

Cosider以下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中没有键,并且@L_@R_801_11280@_14@被声明为可选.它只是跳到其他键.

到目前为止,我没有覆盖初始化器,因为我们拥有RealmOptional Realm Lists等的所有支持扩展.但是现在我必须覆盖init(来自解码器:解码器)以手动解码它并且Realm模型具有50多个@L_@R_801_11280@_14@它(你知道我的意思).

如果我们覆盖初始化器,我觉得使用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兼容,这样我们就不必覆盖初始化器.

解决方法

您可以采取以下措施来解决问题.创建一个支持解码的新类,并将RealmOptional作为其@L_@R_801_11280@_14@.

class OptionalInt64: Object,Decodable {
    private var numeric = RealmOptional<Int64>()

    required public convenience init(from decoder: Decoder) throws {
        self.init()

        let singleValueContainer = try decoder.singleValueContainer()
        if singleValueContainer.decodeNil() == false {
            let value = try singleValueContainer.decode(Int64.self)
            numeric = RealmOptional(value)
        }
    }

    var value: Int64? {
        return numeric.value
    }

    var zeroOrValue: Int64 {
        return numeric.value ?? 0
    }
}

然后,不要在学校班级中使用RealmOptional,而是使用这个新的OptionalInt64类,

class School: Object,Codable {

    @objc dynamic var id: Int64 = 0

    @objc dynamic var name: String?
    @objc dynamic  var numberOfstudents: OptionalInt64?
    var classes = List<Class>()

    enum CodingKeys: String,CodingKey {
       case id
       case name
       case numberOfstudents
       case classes
    }
}

请注意,现在使用RealmNumeric而不是使用RealmOptional?其类型为Optional.由于它是可选的,因此自动解码使用decodeIfPresent方法来解码可选值.如果它不存在于json中,则该值将变为零.

大佬总结

以上是大佬教程为你收集整理的如何使RealmSwift RealmOptional与Swift Codable兼容?全部内容,希望文章能够帮你解决如何使RealmSwift RealmOptional与Swift Codable兼容?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。