无法使用 SwiftUi 上的 List 删除 Realm 上的所有元素

Impossible to delete all element on Realm using a List on SwiftUi

提问人:Valentin 提问时间:9/17/2023 最后编辑:FedorValentin 更新时间:9/17/2023 访问量:34

问:

我有一个列表显示我的所有元素。我想添加一个按钮,从我的列表中删除我的所有元素,也从我的 Realm Database 中删除。 我已经很清楚,删除 Realm 对象后我无法调用它,但是我不明白为什么当我单击“全部删除”按钮时出现此错误:对象已被删除或失效 这是我的代码: 设置视图:

import SwiftUI

struct SettingsView: View {
    
    @Binding var showSetting: Bool
    
    
    @State var allAction01: [Action] = []
    @State var allAction12: [Action] = []
    
    init(showSetting: Binding<Bool>) {
        self._showSetting = showSetting
    }
    
    var body: some View {
        NavigationStack {
                List{
                    
                    Section{
                    
                        Button(action: deleteAll){
                            Text("Delete")
                                .foregroundStyle(.red)
                        }
                            .buttonStyle(.plain)
                    } // Section
                    
                    Section {
                        Text("Liste des actions")
                            .fontWeight(.bold)
                            .font(.system(size: 20))
                    } // Section
                    
                    Section {
                        ForEach(allAction01, id: \.id) { action in
                            Text(action.text)
                        }
                        .onDelete(perform: delete)
                
                    
                    Section {
                        ForEach(allAction12, id: \.id) { action in
                            Text(action.text)
                        }

                } // List
                .onAppear(perform: updateAction)                    
        } // NavigationStack
    } // var body: some View
    
    private func delete(indexSet: IndexSet){
        indexSet.forEach { index in
            DataManager.deleteAction(action: allAction01[index])
        }
        updateAction()
    } // private func delete(indexSet: IndexSet)
    

    private func deleteAll(){
        DataManager.deleteAllActions()
        updateAction()
    }
    
    private func updateAction(){
        allAction01 = DataManager.getActionBetween(inf: 0, sup: 1)
        allAction12 = DataManager.getActionBetween(inf: 1, sup: 2)
   
    }
} // struct SettingsView: View

这是我的

DataManager.deleteAllActions()

    static func deleteAllActions() {
        do {
            try realm.write(){
                let actionToDelete = realm.objects(Action.self)
                realm.delete(actionToDelete)
            }
        } catch {
            print("Error : \(error)")
        }
    }

如果你有任何想法,我真的会帮助我!

PS:我将我的SettingsView显示为覆盖另一个视图的工作表,但是仅删除一个操作时不会引起任何问题。

我尝试删除我的所有操作,我希望有一个空的 BDD 并在此之后列出

Swift SwiftUI 领域

评论


答:

0赞 Jay 9/17/2023 #1

核心问题是使用数组来保存你的 Realm 数据。

虽然从 Realm 中删除对象会删除底层对象,这也会使数组中的对象失效,但它不会从数组中删除索引。

例如,假设以下内容;有一个 PersonClass 对象,在 Realm 中存储了 5 个人。

let personResults = realm.objects(PersonClass.self) //get 5 persons
let personArray = Array(personResults) //instantiate an array with 5 persons

print(personResults.count) //prints 5
print(personArray.count) // also prints 5

try! realm.write {
    realm.delete(personResults) //delete the persons from Realm
}

print(personResults.count) //prints 0 as there are no persons in Realm
print(personArray.count) //print 5 since 5 indexes exist, containing nil objects

有多种方法可以解决此问题

  1. 从 Realm 中删除对象时,也要将其从数组中删除

  2. 使用任一@ObservedRealmObject来处理特定对象,或者在此用例中,使用 @ObservedResults 属性包装器,其定义为:

观察查询结果的集合。您可以执行快速写入 添加到 ObservedResults 集合中,视图会自动更新 当观察到的查询发生更改时,它本身。例如,您可以删除 使用 onDelete 的观察到的狗列表中的狗。

用类似这些内容替换当前的变量将解决此问题

@ObservedResults(Action.self) var actions01
//@State var allAction12: [Action] = []

init(showSetting: Binding<Bool>) {
   self._showSetting = showSetting
}

var body: some View {
   NavigationStack {
      List {
         //use actions01 here for the UI
     

并使用 action01 作为 Lists 数据源。然后,在删除所有操作时,视图将自动更新,因为 actions01 将始终反映基础数据的当前状态 - 删除对象,将其从操作 01 中删除,并且 UI 会相应地更新。

结果可以像只读数组一样处理;遍历它,访问特定的索引等。它不能写入 - 写入 Realm 来更新结果