1
votes

In my multi-dimensional list I am having an issue when I try to delete a Row - Thread 1: Fatal error: Index out of range:

struct Parent: Identifiable {
    let id = UUID()
    let name: String
    var children: [Child]?
}

struct Child: Identifiable {
    let id = UUID()
    let name: String
}

class AppState: ObservableObject {
    @Published var parents: [Parent]
    init() {
        self.parents = [
            Parent(name: "Foo", children: [Child(name: "bar")]),
            Parent(name: "FooBar", children: nil)
        ]
    }
}

struct ContentView: View {
    @EnvironmentObject var appState: AppState
    var body: some View {
        NavigationView {
            List {
                ForEach (0..<appState.parents.count) { parentIndex in
                    NavigationLink (destination: ChildrenView(parentIndex: parentIndex).environmentObject(self.appState)) {
                        Text(self.appState.parents[parentIndex].name) // Thread 1: Fatal error: Index out of range
                    }
                }
                .onDelete(perform: deleteItem)
            }
        }
    }
    private func deleteItem(at indexSet: IndexSet) {
        self.appState.parents.remove(atOffsets: indexSet)
    }
}

struct ChildrenView: View {
    @EnvironmentObject var appState: AppState
    var parentIndex: Int
    var body: some View {
        List {
            ForEach (0..<(appState.parents[parentIndex].children?.count ?? 0)) { childIndex in
                Text(self.appState.parents[self.parentIndex].children![childIndex].name)
            }
        }
    }
}

I rebuilt the situation as I am having this issue in a bigger project with more code. Especially there I am having the issue in the Children View when I try to delete a parent that has children. For parents without children, I am able to remove them. In this code I'm not able to remove a row at all.

I think the issue is somehow related to the parentIndex that is not decreasing while the view is reloading through the Observable Object change.

1
Same again & again... stackoverflow.com/… - Asperi
Thank you - that means ForEach(Range) is constant - when I change it to ForEach (appState.parents) how can I access the index though? - T. Karter
Got it: ForEach (appState.parents.indices, id: \.self) { parentIndex in. Thank you for the reference. - T. Karter

1 Answers

1
votes

The issue occurs because the range in the foreach loop is constant. It must be changed to:

ForEach (appState.parents.indices, id: \.self) { parentIndex in