RealmSwift添加删除确认弹窗后触发RLMException索引越界错误求助
问题排查:RealmSwift添加删除确认弹窗后触发索引越界错误
问题描述
在使用RealmSwift的SwiftUI应用中,原本通过List+ForEach+onDelete调用删除函数的逻辑可正常运行,但添加删除确认弹窗后,触发RLMException错误:"Index 1 is out of bounds (must be less than 1)",重启App后数据已被删除。
错误原因
- SwiftUI List默认行为导致UI与数据源不同步:触发
onDelete时,SwiftUI会自动从List的UI中移除对应行,但此时并未删除Realm数据,仅弹出弹窗。这会导致Realm的Live Results(datasets)仍保持完整,但UI已缺失对应行,后续用保存的索引访问datasets时,索引对应关系错位。 - 保存索引而非对象的风险:Realm的Live Results是实时更新的,索引会随数据增删随时变化,弹窗确认时,之前保存的索引可能已失效。
- 代码笔误:原
showMyHint函数中错误使用未定义的indexSet变量(应为参数indexes),且多余的循环会重复赋值forDeletion。
修复方案
放弃保存删除索引,改为保存要删除的Dataset对象本身(对象主键稳定,不会因数据变化失效),确认后直接删除对象,让Realm的Live Results自动同步UI。
修正后完整代码
ViewModel属性调整
@State private var showHint = false @State private var datasetToDelete: Dataset? // 保存待删除对象,替代原索引集合
List与弹窗逻辑
List { ForEach(datasets) { dataset in Text("\(dataset.name)") } .onDelete(perform: showDeleteConfirmation) } .alert(isPresented: $showHint) { Alert( title: Text("警告"), message: Text("确定要删除这条记录吗?"), primaryButton: .destructive(Text("删除")) { if let dataset = self.datasetToDelete { RealmService.shared.deleteDataset(dataset) self.datasetToDelete = nil } }, secondaryButton: .cancel() { self.datasetToDelete = nil } ) } func showDeleteConfirmation(at indexes: IndexSet) { // 取出待删除的对象(处理单条删除场景) guard let index = indexes.first else { return } self.datasetToDelete = datasets[index] self.showHint = true }
RealmService删除函数(保持原逻辑不变)
func deleteDataset(_ dataset: Dataset) { do { if let forDeletion = realm.object(ofType: Dataset.self, forPrimaryKey: dataset.id) { try realm.write { realm.delete(forDeletion) } } else { print("DATASET not found or already deleted") } } catch { print("Error deleting DATASET: \(error.localizedDescription)") } }
说明
- 触发
onDelete时直接取出对应对象保存,避免索引失效问题。 - 弹窗确认后直接删除对象,Realm的Live Results会自动更新,List UI同步刷新,无索引错位风险。
- 上述代码处理单条删除场景,若需支持多选删除,可调整为保存
[Dataset]数组并修改弹窗逻辑。
内容的提问来源于stack exchange,提问作者user2836375
相关产品推荐
相关产品推荐

