Index out of range, SwiftUI

Hello

import SwiftUI


enum When: String {
    case Today
    case Week
    case Month
    case Year
}


struct ChartView: View {
    
    var when: When
    @EnvironmentObject var millilitriInseritiModel: MillilitriInseritiModel
    var valoriAsseX: [String]{
        if when == When.Week{
            return   ["M", "T", "W", "T", "F", "S", "S"]
        } else if when == When.Month{
            return   ["7", "14", "21", "28"]
        } else if when == When.Year{
            return  ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"]
        }
        
        return []
    }
    
    var valoriAsseY: [Double]{
        return []
    }
    
    var dates: [Date] = [Date(), Date().addingTimeInterval(86400), Date().addingTimeInterval(86400 * 2)]
    @State var valori: [Double] = [1000, 2000, 3000, 1000, 2000, 1000, 2000, 3000, 1000, 2000, 3000]
    
    var altezzaRettangolo: [Double]?{
        var altezze: [Double] = []
        for i in 0..<valori.count{
            altezze.append(valori[i])
        }
        
        return altezze
    }
    
    @State var animation: Bool = false
    
    var body: some View{
        HStack(alignment: .bottom, spacing: 8, content: {
            ForEach(valoriAsseX.indices){ i in
                VStack{
                    RoundedRectangle(cornerRadius: 3)
                        .fill(LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .top, endPoint: .bottom))
                        .frame(width: 40, height: animation ? CGFloat(altezzaRettangolo?[i] ?? 0) / 7 : 0)
                        .animation(.easeInOut)
                    
                    Text(valoriAsseX[i])
                        .fontWeight(.semibold)
                        .multilineTextAlignment(.leading)
                        .onTapGesture {
                            withAnimation{
                                valori[i] += 100
                            }
                        }
                }
            }
        })
        .padding()
        .onAppear {
            animation = true
        }
        .onDisappear {
            animation = false
        }
    }
}

struct ChartView_Previews: PreviewProvider {
    static var previews: some View {
        ChartView(when: When.Year)
    }
}

As you might notice, in the previews I set when to When.Year, that is crashing the app because the array valoriAsseX is bigger than the array altezzaRettangolo, so when I iterate it in the ForEach loop it crashes, I can't find any way to solve this, I tried an if let but it is crashing anyway, any ideas?

Thank you

Answered by Claude31 in 678036022

For sure the problem is not on tapGesture or animation but the access to the array element. Focus is on valori[x]

So, everywhere you want to access valori[i], make the test:

      if i < valori.count { valori[i] += 100 } 

There are 11 items in valori but there are 12 months.

Did you forget one value in valori ?

if let is not done for that, it is for testing nil.

The ** values ** array is just a placeholder for now, it can be empty or have N elements, I just want to assign 0 to values[i] when it doesn't exists, but when I try it it crashes anyway

Son

test that index is valid:

 .onTapGesture {
   withAnimation {
      if i < valori.count { valori[i] += 100 } 
}

The problem is not the onTapGesture (the onTapGesture is also a placeholder), the problem is that valori has fewer elements than valoriAsseX, I want that if valori[I] doesn't exist it becomes 0. Don't look at the onTapGesture, it's not a problem

Accepted Answer

For sure the problem is not on tapGesture or animation but the access to the array element. Focus is on valori[x]

So, everywhere you want to access valori[i], make the test:

      if i < valori.count { valori[i] += 100 } 
Index out of range, SwiftUI
 
 
Q