You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Decodable协议初始化Realm对象?附代码示例

搞定Realm对象继承+Decodable实现的问题

先给你捋捋原代码里的几个明显坑:

  1. required init() { self.init() } 这是纯纯的递归调用啊,一运行直接崩溃,得改成调用父类的空初始化super.init()
  2. 那些init(realm:schema:)和init(value:schema:)是Realm内部用的方法,咱们自己不用实现,删掉就行,多写反而容易出问题
  3. Realm的List类型默认不支持Decodable解码,得自己写逻辑把JSON数组转成List
  4. 子类B得处理自己的CodingKeys,还要在解码时先搞定父类的属性,再处理自己的

下面是修正后的完整代码,带注释说明:

父类A的正确实现

import RealmSwift

class A: Object, Decodable {
    // Realm的List属性,默认是空的
    let listA = List<Int>()
    
    // 只保留Realm要求的空初始化,调用父类的init
    required override init() {
        super.init()
    }
    
    // 对应JSON里的字段名,这里假设JSON里的键是"list_a",你可以根据实际情况改
    private enum CodingKeys: String, CodingKey {
        case listA = "list_a"
    }
    
    // Decodable要求的初始化方法
    required convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 把JSON数组解码成Swift数组,再转成Realm的List
        if let intArray = try container.decodeIfPresent([Int].self, forKey: .listA) {
            listA.append(objectsIn: intArray)
        }
    }
}

子类B的正确实现

class B: A {
    let listB = List<Int>()
    
    // 子类自己的CodingKeys,对应JSON里的"list_b"
    private enum CodingKeys: String, CodingKey {
        case listB = "list_b"
    }
    
    // 子类的空初始化,调用父类init
    required init() {
        super.init()
    }
    
    // 子类的解码初始化,要先处理父类的属性
    required convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 先调用父类的解码逻辑,确保listA被正确初始化
        try super.init(from: decoder)
        
        // 处理自己的listB属性,和父类逻辑一样
        if let intArray = try container.decodeIfPresent([Int].self, forKey: .listB) {
            listB.append(objectsIn: intArray)
        }
    }
}

几个关键要点说明

  • 递归初始化问题:原代码里的self.init()会无限循环调用自己,必须换成super.init()来调用Realm Object的内置空初始化
  • List解码逻辑:因为Realm的List没有默认实现Decodable,所以我们先把JSON里的数组转成Swift标准数组,再用append(objectsIn:)把元素批量添加到List中
  • 继承解码顺序:子类解码时一定要先调用super.init(from:)处理父类的属性,不然父类的List会是空的
  • 字段可选性:如果JSON里的数组字段是必传的,把decodeIfPresent改成decode就行,这样字段缺失时会直接抛出解码错误,方便排查问题

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:13:11