Ramin
Ramin

Reputation: 11

Swiftui updating menu component lists dynamically

I have two menu components and need to update the number of elements in the second menu once a selection is made in the fist menu component. Here is a simplified sample code:

import SwiftUI

struct ContentView: View {
    
    @State var menu1List: [Int]
    @State var menu2List: [String]
    @State var currentIndex: Int
    
    init() {
        _menu1List = State(initialValue: [1, 2, 3, 4, 5, 6 , 7, 8])
        _menu2List = State(initialValue: ["A", "B", "C", "D", "E", "F", "G", "H"])
        _currentIndex = State(initialValue: 0)
    }
    
    var body: some View {
        VStack(alignment: .leading) {
            MenuView(menu1List: $menu1List, menu2List: $menu2List, currentIndex: $currentIndex)
            ForEach(menu2List.indices) { index in
                Text("Item \(menu2List[index])") \\Menu 1 selection in MenuView causes index out of range exception.
            }
            Spacer()
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct MenuView : View {
    
    @Binding var menu1List: [Int]
    @Binding var menu2List: [String]
    @Binding var currentIndex: Int

    var body: some View {
        HStack {
            Menu {
                ForEach(menu1List.indices) { index in
                    Button(action: {
                        menu2List = ["A", "B", "C", "D"]
                    }
                    ) {
                        Text("\(menu1List[index])")
                    }
                }
            } label: {
                Text("Menu1")
                Image(systemName: "chevron.down.circle")
            }
            
            Spacer()

            Menu {
                ForEach(menu2List.indices) { index in
                    Button(action: {
                        currentIndex = index
                    }
                    ) {
                        Text("\(menu2List[index])")
                    }
                }
            } label: {
                Text("Menu2")
                Image(systemName: "chevron.down.circle")
            }
        }
        .padding()
    }
}

When I lower the number of elements in Menu 2 I get an Index out of range exception as indicated in the code. Is there any way to fix this? I would greatly appreciate any help on this.

Upvotes: 1

Views: 1273

Answers (1)

Asperi
Asperi

Reputation: 257789

You used static variant of ForEach constructor (ie it expected that data is not changed), but if you want to change content of ForEach you must use dynamic one (with id:)

    ForEach(menu2List.indices, id: \.self) { index in    // << here !!
        Text("Item \(menu2List[index])")
    }

Upvotes: 1

Related Questions