0
votes

I'm having this issue where onDelete works in one view, but it doesn't work in a different view when I'm doing the same thing.

In the first view, it creates an empty array.

@State var funds: [Account.Fund] = []

When a user creates a fund, it prints them out onto the list using a ForEach.

if funds.count > 0{
                        ForEach(funds.indices, id: \.self) { index in
                            StandardRowView(word: funds[index].name, number: funds[index].balance)
                        }
                        .onDelete(perform: { indexSet in
                            funds.remove(atOffsets: indexSet)
                        })

                    }

This works fine. When I swipe and press delete, it will delete without any issues. However, to create a fund, the user must go to a different view. That "funds" variable is passed through.

NavigationLink(
                        destination: AddFundView(funds: $funds, savingsBalance: $balance),
                        label: {
                            Text("Funds")
                        })

In AddFundView its a Binding.

@Binding var funds: [Account.Fund]

Now in AddFundView, it will print them to a list as the user adds them. The code is similar to before, but it does have some extra stuff so they can edit the amount the entered.

ForEach(funds.indices, id: \.self) { index in
                //StandardRowView(word: funds[index].name, number: funds[index].balance)
                
                HStack{
                    Text(funds[index].name)
                    Spacer()
                    TextField("Amount", value: $funds[index].balance, formatter: NumberFormatter.currency)
                        .keyboardType(.numbersAndPunctuation)
                        .multilineTextAlignment(.trailing)
                        .onChange(of: funds[index].balance, perform: { value in
                            
                            //Resets the fund balance if it exceeds the savings balance
                            if value > savingsBalance || fundsTotal > savingsBalance{
                                funds[index].balance = copy[index].balance
                            }
                        })
                }
            }
            .onDelete(perform: { indexSet in
                funds.remove(atOffsets: indexSet)
            })

When you use the onDelete in AddFundView, I get this error.

Swift/ContiguousArrayBuffer.swift:580: Fatal error: Index out of range
2021-04-23 20:06:56.400433-0400 WMMG[12180:9619685] Swift/ContiguousArrayBuffer.swift:580:     Fatal error: Index out of range

I'm a bit confused, because this same behavior is happening elsewhere in the application. I've seen some previous questions and answers about this, and it mentioned it having to do with them using "indices". However, it works when using that, just not every time for some reason that I'm not understanding. Can anybody help me figure this out?

UPDATE: It seems to be related to the TextField. If I comment that out, it works fine. I believe it has to do with this part of the TextField. I'm not sure how to get the behavior I want yet though.

value: $funds[index].balance
1

1 Answers

1
votes

The ForEach returns each item as index (from 'index in'), you can use that item instead of accessing that item in the array. You just need to pass the funds array itself to the ForEach.

I got a little confused with the copy part, but try this:

ForEach(funds, id: \.self) { index in
            //StandardRowView(word: index.name, number: index.balance)
            
            HStack{
                Text(index.name)
                Spacer()
                TextField("Amount", value: $index.balance, formatted: NumberFormatter.currency)
                    .keyboardType(.numbersAndPunctuation)
                    .multilineTextAlignment(.trailing)
                    .onChange(of: index.balance, perform: { value in
                        
                        //Resets the fund balance if it exceeds the savings balance
                        if value > savingsBalance || fundsTotal > savingsBalance{
                            index.balance = copy[index].balance // not sure here
                        }
                    })
            }
        }
        .onDelete(perform: { indexSet in
            funds.remove(atOffsets: indexSet)
        })