简体   繁体   English

SwiftUI.onDelete 抛出致命错误:索引超出范围

[英]SwiftUI .onDelete throws Fatal Error: Index out of range

I have list of Account s that each of them has a detail page and they are connected through @Binding in the AccountDetailView .我有一个Account列表,它们每个都有一个详细信息页面,并且它们通过AccountDetailView中的@Binding连接。 Current code work well, updates are fine.当前代码运行良好,更新很好。 No problem at all.完全没有问题。 However when I added the onDelete modifier to the ForEach below and tried swipe to delete gesture in app, it crashes and says Fatal Error: Index out of range twice.但是,当我将onDelete修饰符添加到下面的ForEach并尝试swipe to delete应用程序中的手势时,它会崩溃并显示两次Fatal Error: Index out of range

I made some search and learned that ForEach somehow does not get notified -or ignores it, idk much detail- and looks for the last index of the array.我进行了一些搜索并了解到ForEach以某种方式没有得到通知 - 或者忽略它,idk 很多细节 - 并寻找数组的最后一个索引。 In the end, it can not find it and throws the error.最后,它找不到它并抛出错误。

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)
        }
    }
}

With keeping id: \.self parameter in place it throws the error at the AppDelegate , when I try to remove the parameter, the app works fine but again onDelete it throws the same error at NavigationLink 's row above.id: \.self参数保持在适当位置时,它会在AppDelegate引发错误,当我尝试删除参数时,应用程序工作正常,但再次onDelete它会在NavigationLink上面的行中引发相同的错误。

Here is the AccountDetailView这是AccountDetailView

struct AccountDetailView: View {

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

    var body: some View {
        ...
    }
}

Finally Account class conforms to Codable , NSObject , Indentifiable and some other class.最后Account class 符合CodableNSObject 、 Indentifiable 和其他一些Indentifiable I did not want to give all the code just because did not want make the question complicated and hard to examine.我不想仅仅因为不想让问题变得复杂和难以检查而给出所有代码。 If requested, I will provide any part of the code.如果需要,我将提供代码的任何部分。 Thanks in advance.提前致谢。

Found a solution.找到了解决方案。 With respect to the this answer to a related question, it came clear.关于对相关问题的这个答案,它很清楚。 Apperantly, with using the .indices to fullfill ForEach makes onDelete not to work.显然,使用.indices ForEach会使onDelete不起作用。 Instead, going through directly Elements of an array and creating proxy Bindings is working.相反,直接通过数组Elements并创建代理Bindings是有效的。

To be it more clear here are the ContentView , DetailView and an extension for Binding to avoid cluttering view.这里更清楚的是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扩展

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

This way, both onDelete and publishing changes by directly updating the object inside detail view will work.这样,通过直接更新 object 内部详细视图的onDelete和发布更改都将起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM