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

如何在Swift结构体中让ObjectBox反向链接正常保存?

ObjectBox 关联关系同步异常问题

场景还原

定义的实体结构体

struct FFF: Entity, Identifiable {
    let id: Id
    let name: String
    // objectbox: backlink = "f"
    var ns: ToMany<NNN>
}
struct NNN: Entity, Identifiable {
    let id: Id
    let name: String
    var f: ToOne<FFF>
}

关联操作代码

let path = NSTemporaryDirectory() + "/d"
let store = try Store(directoryPath: path)
let fffBox = store.box(for: FFF.self)
let nnnBox = store.box(for: NNN.self)
try fffBox.removeAll()
try nnnBox.removeAll()
let f0 = try fffBox.put(struct: FFF(id: 0, name: "X", ns: nil))
let n0 = try nnnBox.put(struct: NNN(id: 0, name: "Y", f: nil))
n0.f.target = f0
let n1 = try nnnBox.put(struct: n0)
let f1 = try fffBox.put(struct: f0)
print("f0 = \(f0)")
print("n0 = \(n0)")
print("f1 = \(f1)")
print("n1 = \(n1)")
let nstest = f1.ns
print("nstest = \(nstest)")

实际输出

f0 = FFF(id: 1, name: "X", ns: ToMany<NNN>(unresolved))
n0 = NNN(id: 1, name: "Y", f: ToOne<FFF>(.stored(id: EntityId<FFF>(1), target: FFF(id: 1, name: "X", ns: ToMany<NNN>(unresolved)))))
f1 = FFF(id: 1, name: "X", ns: ToMany<NNN>(unresolved))
n1 = NNN(id: 1, name: "Y", f: ToOne<FFF>(.stored(id: EntityId<FFF>(1), target: FFF(id: 1, name: "X", ns: ToMany<NNN>(unresolved)))))
nstest = (unresolved)

问题

设置ToOne属性建立关联后,ToMany反向关联始终显示为空;反过来设置ToMany属性时,ToOne属性会变为nil,不清楚操作哪里出错,按照官方文档的结构体使用方式调用方法,认为流程是正确的。


问题分析与解决方案

核心错误点

  1. 值类型特性导致的同步失效:使用struct作为实体(值类型),修改n0.f.target = f0后,原f0实例不会自动感知关联变化——值类型的修改是创建新实例,不会同步到已存储的对象中。
  2. 冗余的实体存储操作:修改n0并存储为n1后,又存储了未做任何修改的f0为f1,这一步完全多余,且不会触发反向关联更新。
  3. 延迟加载的误解:ToMany默认是延迟加载的,直接打印会显示unresolved,必须主动触发加载(比如访问count或遍历元素)才能获取实际关联数据。

修正后的代码

let path = NSTemporaryDirectory() + "/d"
let store = try Store(directoryPath: path)
let fffBox = store.box(for: FFF.self)
let nnnBox = store.box(for: NNN.self)
try fffBox.removeAll()
try nnnBox.removeAll()

// 创建并存储FFF实体
let f0 = try fffBox.put(struct: FFF(id: 0, name: "X", ns: nil))

// 创建NNN实体时直接关联FFF,再存储
var n0 = NNN(id: 0, name: "Y", f: ToOne(target: f0))
let n1 = try nnnBox.put(struct: n0)

// 从数据库重新获取FFF实体,此时反向关联已被维护
let f1 = try fffBox.get(id: f0.id)!

// 触发ToMany加载并查看结果
let nstest = f1.ns
print("nstest 关联数量: \(nstest.count)")
for n in nstest {
    print("关联的NNN实体: \(n)")
}

关键说明

  • 值类型的修改逻辑:由于struct是值类型,修改关联后必须重新存储该实体,而不是修改旧实例后存储原关联对象。
  • 反向关联加载方式:ToMany属性需要通过访问元素或count触发数据库查询,加载完成后才能看到实际数据,直接打印只会显示未解析状态。
  • 避免冗余操作:无需重复存储未修改的实体,ObjectBox会在存储ToOne关联的实体时自动维护反向ToMany关系,但需要重新从数据库获取实体才能看到更新后的关联。

内容的提问来源于stack exchange,提问作者Jeff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:16:03