使用Realm删除SwiftUI列表行崩溃:索引越界问题求助
解决SwiftUI + Realm分组列表删除时索引越界问题
问题原因
你遇到的崩溃是因为直接通过section[index]获取待删除对象时,Realm的ObservedSectionedResults是响应式数据源,删除操作触发后数据源会实时更新,导致当前section的元素快照已经过时,索引和实际元素数量不匹配,尤其是删除非末尾行时,索引错位引发越界。
解决方案
方案1:使用安全下标访问元素
先给集合添加一个安全下标扩展,避免直接访问越界索引:
extension Collection { subscript(safe index: Index) -> Element? { return indices.contains(index) ? self[index] : nil } }
然后修改onDelete的实现:
.onDelete(perform: { indexSet in do { guard let realm = realmManager.localRealm else { return } guard let index = indexSet.first else { return } // 安全获取待删除对象 guard let qualifierToDelete = section.elements[safe: index] else { return } try realm.write { realm.delete(qualifierToDelete) } } catch { print("Error deleting qualifier: \(error.localizedDescription)") } })
方案2:使用ObservedSectionedResults官方方法定位元素
通过ObservedSectionedResults提供的element(at:)方法,结合分组索引和元素索引获取最新的对象,这是最可靠的方式:
修改外部ForEach来获取分组的索引:
ForEach(Array(qualifiers.enumerated()), id: \.element.id) { sectionIndex, section in Section(header: Text(section.key ? "Custom" : "Default")) { // 修正:用section.key替代section.id,分组key对应isCustom字段值 ForEach(section) { qualifier in Text(qualifier.title) } .onDelete(perform: { indexSet in do { guard let realm = realmManager.localRealm else { return } guard let elementIndex = indexSet.first else { return } // 通过官方方法获取待删除对象 let targetIndex = SectionedResultsIndex(section: sectionIndex, element: elementIndex) let qualifierToDelete = qualifiers.element(at: targetIndex) try realm.write { realm.delete(qualifierToDelete) } } catch { print("Error deleting qualifier: \(error.localizedDescription)") } }) } }
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

