3

I have a environment object that is an array, and a panel in my settings page where the user can add/remove values to the array...here is the list of items in the array displayed visually for the user:

ScrollView {
    VStack {
        ForEach(self.env.numbers.indices, id: \.self) { number in
            ZStack {
                HStack {
                    Text("#\(number +  1): ")
                        .font(Font.custom(K.font.montserratMedium, size: 17.0))
                        .foregroundColor(Color(K.SettingsTextColor))
                    
//                                            Spacer()
                    
                    NumberTextField(self.env.numbers[number], text: self.$env.numbers[number])
        
                }
                
                
                
            }
            
        }
    }
}

and at the bottom of my view is a toggle to change the number of items in the array:

Stepper(onIncrement: {
    
    self.env.numbers.append("12345")
    print("default number should be added")
    print(self.env.numbers.indices)
    print(self.env.numbers)
    print("count = \(self.env.numbers.count)")
    
},
        
        onDecrement: {
            
            if self.env.numbers.count != 0 {
                print("number should be removed")
                self.env.numbers.removeLast(1)
//              also tried self.env.numbers = self.env.numbers.droplast() but this didnt work
                print(self.env.numbers.indices)
                print(self.env.numbers)
                print("count = \(self.env.numbers.count)")
                
}

the NumberTextField view is a UIKit UITextField wrapper, and seems to work fine. Everything about this works fine until I try to decrease the stepper, and I get the Index out of range error (which surprisingly shows the error happening in the app delegate)...any ideas how to fix this?

Benjamin B.
  • 521
  • 7
  • 15
  • 2
    See if this helps: https://stackoverflow.com/a/63083658/968155 – New Dev Aug 12 '20 at 19:32
  • sadly no, it is breaking my stepper view...I was trying to implement this solution but getting additional errors I can't get rid of: https://stackoverflow.com/questions/58984109/fatal-error-index-out-of-range-when-deleting-bound-object-in-view/59007863#59007863 – Benjamin B. Aug 12 '20 at 19:46
  • 2
    It shouldn't be related to the stepper view. What fails is (likely) this: `self.$env.numbers[number]`. The solution [here](https://stackoverflow.com/a/63083658/968155) would allow you to wrap the views inside the `ForEach` and get a binding directly to the element in `numbers`, instead of using the index. – New Dev Aug 12 '20 at 19:51
  • so does "binding" replace "numbers" in my foreach? I got a "Cannot convert value of type 'Binding' to expected argument type 'Int'" error when writing ` NumberTextField(self.env.forceNumbers[binding], text: self.$env.forceNumbers[binding]) ` ...this is still a bit over my head but i think im almost there... – Benjamin B. Aug 12 '20 at 20:04
  • No, `binding` replaces `self.$env.numbers[number]`, and `binding.wrappedValue` replaces `self.env.numbers[number]` – New Dev Aug 12 '20 at 20:08
  • HOLY CRAP IT WORKED!!!! Yeah this is still over my head but this is beyond helpful...thank you again!! – Benjamin B. Aug 12 '20 at 20:14
  • 1
    Cool. Upvote if it helped ;) As discussed in the other question, this might be a bug in SwiftUI where behind the scenes SwiftUI still tries to access - out of order - a binding to the now deleted value. We would have expected `ForEach` to re-compute the indices after deletion first, but that's not what happens, for some reason. The solution basically found a way around – New Dev Aug 12 '20 at 20:20
  • makes sense, its weird because the range is being defined in the environment, and it seems like its removing the item first then using the old range to check, but this works brilliantly and will do until apple gets themselves together... – Benjamin B. Aug 12 '20 at 21:43
  • 1
    hehe.. I meant, upvote the [other answer](https://stackoverflow.com/a/63083658/968155) so it will appear higher for others to notice – New Dev Aug 12 '20 at 21:48
  • I'm having the same problem. I even substituted a simple static array and it still crashes. This doesn't happen with the primary picker forEach. Only the secondary picker forEach that's loaded to replace the primary picker. It has to be a BUG. – Frederick C. Lee Oct 02 '20 at 23:51
  • Same error at this stackoverflow question - https://stackoverflow.com/q/65375372/2641380 (Added comment here so both the questions get linked.) – SHS Dec 20 '20 at 14:09

0 Answers0