如何在Realm数据模型中设置弱引用并构建无循环引用的账单拆分模型
Realm 账单拆分应用模型关系设计方案
核心模型结构
按照需求,我们可以通过Realm的List(强引用一对多)和LinkingObjects(弱引用反向关联)构建关系,同时避免循环引用。以下是具体的Swift实现:
Meal 模型(账单主对象)
作为顶层对象,持有该账单下所有人员和菜品的集合:
import RealmSwift class Meal: Object { @Persisted(primaryKey: true) var id: UUID = UUID() @Persisted var name: String = "" // 该账单包含的所有就餐人员 @Persisted var people = List<Person>() // 该账单包含的所有菜品 @Persisted var items = List<Item>() }
Person 模型(就餐人员)
关联所属账单下的菜品,仅保留必要的正向关联:
class Person: Object { @Persisted(primaryKey: true) var id: UUID = UUID() @Persisted var name: String = "" // 该人员需要分摊的菜品集合 @Persisted var assignedItems = List<Item>() // 可选:反向关联所属账单(弱引用,无循环风险) @Persisted(originProperty: "people") var meal: LinkingObjects<Meal> }
Item 模型(菜品)
仅保留与账单的反向关联(若不需要可省略),不添加对Person的正向引用:
class Item: Object { @Persisted(primaryKey: true) var id: UUID = UUID() @Persisted var name: String = "" @Persisted var price: Double = 0.0 // 可选:反向关联所属账单(弱引用,无循环风险) @Persisted(originProperty: "items") var meal: LinkingObjects<Meal> // 注意:不要添加`List<Person>`类型的属性,避免与Person形成双向强引用循环 }
避免循环引用的关键逻辑
账单与子对象的关系:
Meal通过List持有Person和Item的强引用,而Person/Item通过LinkingObjects反向关联Meal。LinkingObjects是Realm提供的弱引用类型,不会增加对象的引用计数,因此不会导致Meal与Person/Item之间的循环引用。人员与菜品的关系:
仅在Person中通过List<Item>持有菜品的引用,Item中不添加对Person的正向引用。如果业务需要从菜品反向查询哪些人员分摊了它,可以使用LinkingObjects实现弱引用反向关联,示例如下:// 在Item模型中添加(可选) @Persisted(originProperty: "assignedItems") var assignedBy: LinkingObjects<Person>这种方式依然是弱引用,不会造成Person与Item之间的循环引用。
数据操作示例
确保添加到Person的assignedItems中的菜品,已经属于同一个Meal的items集合,保证数据一致性:
let realm = try! Realm() try! realm.write { // 创建账单 let dinnerMeal = Meal() dinnerMeal.name = "周末晚餐" // 创建菜品并加入账单 let steak = Item() steak.name = "西冷牛排" steak.price = 98.0 dinnerMeal.items.append(steak) let pasta = Item() pasta.name = "意大利面" pasta.price = 42.0 dinnerMeal.items.append(pasta) // 创建人员并分配菜品 let alice = Person() alice.name = "Alice" alice.assignedItems.append(steak) alice.assignedItems.append(pasta) dinnerMeal.people.append(alice) let bob = Person() bob.name = "Bob" bob.assignedItems.append(steak) dinnerMeal.people.append(bob) // 将账单写入Realm realm.add(dinnerMeal) }
内容的提问来源于stack exchange,提问作者Halpo
相关产品推荐
相关产品推荐

