Realm中创建对象引用的正确方法 健身应用数据关联问询
最优实现方案
优先采用Realm原生的对象关联关系替代当前逗号分隔ID字符串的存储方案,既可以大幅简化查询代码,还能利用Realm本身的查询优化提升读取性能,适配你后续的数据筛选需求。
步骤1:调整数据模型
将原来存储关联ID的String类型字段替换为Realm内置的List类型,直接存储关联对象的引用,无需自行维护ID映射逻辑:
// 器材类示例,确保你的现有Equipment/Muscle类符合Realm模型规范 class Equipment: Object { @Persisted(primaryKey: true) var id: Int = 0 @Persisted var name: String = "" // 可选:添加反向关联,可快速查询某器材对应的所有动作 @Persisted(originProperty: "equipments") var linkedExercises: LinkingObjects<Exercise> } class Muscle: Object { @Persisted(primaryKey: true) var id: Int = 0 @Persisted var name: String = "" // 可选:反向关联,查询某肌肉对应的所有动作 @Persisted(originProperty: "muscles") var linkedExercises: LinkingObjects<Exercise> } // 改造后的Exercise主类 class Exercise: Object { @Persisted(primaryKey: true) var exerciseID: Int = 0 @Persisted var name: String = "" @Persisted var category: Int // 替换原String字段,直接存储关联对象集合 @Persisted var equipments: List<Equipment> @Persisted var muscles: List<Muscle> @Persisted var instruction: String @Persisted var gif: String? @Persisted var image: String? = nil convenience init( name: String, category: Int, equipments: [Equipment], muscles: [Muscle], instruction: String, gif: String?, image: String? ) { self.init() self.name = name self.category = category self.equipments.append(objectsIn: equipments) self.muscles.append(objectsIn: muscles) self.instruction = instruction self.gif = gif self.image = image } }
因为你的初始数据是预置的,只需要在制作预置Realm文件时直接写入关联关系即可,首次启动替换默认Realm文件的逻辑无需修改。
步骤2:简化查询逻辑
改造后无需再做字符串拆分、ID转换、单独查询关联对象的操作,可直接读取关联属性:
// 直接持有Realm的Results集合,自动同步数据 var exercises: Results<Exercise>? func getAllExercises() { exercises = RealmService.shared.realm.objects(Exercise.self) // 示例:获取所有动作关联的全部器材,自动去重 let allEquipments = Array(Set(exercises?.flatMap(\.equipments) ?? [])) // 示例:获取第一个动作的所有关联肌肉 let firstMuscles = exercises?.first?.muscles }
关联筛选也可以直接用Realm的原生查询语法实现,比如筛选所有需要哑铃(器材ID=1)且练胸肌(肌肉ID=2)的动作:
let targetExercises = RealmService.shared.realm.objects(Exercise.self) .filter("equipments.id == 1 AND muscles.id == 2")
关于「存值还是存引用」的选择
- 若你的器材、肌肉数据永远不会变更,也不需要做反向查询、关联筛选,可简化为直接存储
List<String>类型的器材/肌肉名称,比你当前存逗号分隔字符串的方案更简洁,也无需额外维护关联类 - 若后续可能给器材/肌肉新增属性(比如器材图标、肌肉示意图)、需要做灵活的关联筛选,优先选择对象引用方案,扩展性和查询效率更高
内容的提问来源于stack exchange,提问作者TeddyKen
相关产品推荐
相关产品推荐

