SwiftUI .onDelete throws Fatal Error: Index out of range

SwiftUI .onDelete throws Fatal Error: Index out of range

我有 Account 个列表,每个列表都有一个详细信息页面,它们通过 AccountDetailView 中的 @Binding 连接。当前代码运行良好,更新很好。完全没有问题。但是,当我将 onDelete 修饰符添加到下面的 ForEach 并尝试在应用程序中使用 swipe to delete 手势时,它崩溃并显示 Fatal Error: Index out of range 两次。

我进行了一些搜索,了解到 ForEach 不知何故没有收到通知 - 或者忽略它,idk 很多细节 - 并查找数组的最后一个索引。最后,它找不到它并抛出错误。

List {
    Section(header: Text(String.empty), footer: Text(Strings.SectionFooters.accountListFooter.value)) {
        ForEach(self.accountsModel.accounts.indices, id:\.self) { idx in
            NavigationLink(destination: AccountDetailView(account: self.$accountsModel.accounts[idx])) {
                AccountRow(account: self.$accountsModel.accounts[idx])
            }
        }.onDelete { (set) in
            self.accountsModel.accounts.remove(atOffsets: set)
        }
    }
}

在保留 id: \.self 参数的情况下,它会在 AppDelegate 处抛出错误,当我尝试删除该参数时,应用程序运行正常,但再次 onDelete 它抛出相同的错误上面 NavigationLink 行的错误。

这是AccountDetailView

struct AccountDetailView: View {

    @EnvironmentObject var accountsModel: AccountsViewModel
    @Binding var account: Account
    @State var isEditing: Bool = false

    var body: some View {
        ...
    }
}

最后 Account class 符合 CodableNSObjectIndentifiable 和其他一些 class。我不想给出所有的代码只是因为不想让问题变得复杂和难以检查。如果需要,我将提供代码的任何部分。提前致谢。

找到解决办法。关于这个 到一个相关问题,它很清楚。显然,使用 .indices 来填充 ForEach 会使 onDelete 不起作用。相反,直接通过数组 Elements 并创建代理 Bindings 是有效的。

这里更清楚的是 ContentViewDetailViewBinding 的扩展以避免混乱的视图。

ContentView

struct ContentView: View {

    @EnvironmentObject var store: DataStore

    var body: some View {
        NavigationView {
            List {
                ForEach(self.store.data, id: \.id /*with or without id*/) { (data) in
                    NavigationLink(destination: DetailView(data: /*created custom initializer*/ Binding(from: data))) {
                        Text(data.name)
                    }
                }.onDelete { (set) in
                    self.store.data.remove(atOffsets: set)
                }
            }.navigationBarTitle("List")
        }
    }
}

DetailView

struct DetailView: View {

    @Binding var data: MyData

    var body: some View {
        List {
            TextField("name", text: self.$data.name)
        }
        .navigationBarTitle(self.data.name)
        .listStyle(GroupedListStyle())
    }
}

Binding 分机

extension Binding where Value: MyData {
    init(from data: MyData) {
        self.init(get: {
            data as! Value
        }) {
            dataStore.data[dataStore.data.firstIndex(of: data)!] = [=12=]
        }
    }
}

这样,onDelete 和通过直接更新详细视图中的对象来发布更改都将起作用。