SwiftUI .onDelete 抛出致命错误:索引超出范围 [英] SwiftUI .onDelete throws Fatal Error: Index out of range

查看:32
本文介绍了SwiftUI .onDelete 抛出致命错误:索引超出范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have list of Accounts that each of them has a detail page and they are connected through @Binding in the AccountDetailView. 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.

我进行了一些搜索并了解到 ForEach 以某种方式没有得到通知 - 或忽略它,发现很多细节 - 并查找数组的最后一个索引.最后,它找不到它并抛出错误.

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

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

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.

这是AccountDetailView

struct AccountDetailView: View {

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

    var body: some View {
        ...
    }
}

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

Finally Account class conforms to Codable, NSObject, Indentifiable and some other class. 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.

推荐答案

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

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. Instead, going through directly Elements of an array and creating proxy Bindings is working.

为了更清楚,这里是 ContentViewDetailViewBinding 的扩展以避免混乱的视图.

To be it more clear here are the ContentView, DetailView and an extension for Binding to avoid cluttering view.

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

绑定扩展

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

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

This way, both onDelete and publishing changes by directly updating the object inside detail view will work.

这篇关于SwiftUI .onDelete 抛出致命错误:索引超出范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆