How do I use a for loop in a toolbar view?

53 Views Asked by At

I have written something like the code below. Creating a struct for menu information (MenuInfo) and created a few menu items in an array of MenuInfo's. I'm now trying to walk over those to create the menus. (For now just printing details from the array). Code below is to show the concept and may not compile. I get the following error:

Static method 'buildExpression' requires that 'ToolbarItemGroup<Menu<Text, TupleView<(Button, Button, Divider, Button)>>>' conform to 'View'

Not sure what I have done wrong but the issue goes away when I comment out the entire ToolbarItemGroup -> for section. The error prints next to the first ToolbarItemGroup which of course is correct and the error is not specific.

enum Tools {
   case a, b
}

struct MenuInfo {
  var name: String
  var image: String
  var tool: Tools

  init(_ name: String,_ image: String,_ tool: Tools ) {
     self.name      = name
     self.image     = image
     self.tool      = tool
  }
}

private var qMark = "questionmark"

//   Name           Image   Tool
var myMenu = [
   MenuInfo( "A",   qMark,  .a ),
   MenuInfo( "B",   qMark,  .b )
]

struct ContentView: View {
   @State private var curToolSet = ToolSet.eng
   @State private var curTool = Tools.arrow

   var body: some View {
       VStack {
           Text( "Content" )
               .toolbar {
                   ToolbarItemGroup {
                       Menu(content: {
                           Button( "Hi" ) { curToolSet = .eng }
                       }, label:{ Text( "Engineering" )})
                   }

//                  ToolbarItemGroup {
//                      for curMenu in myMenu {
//                          Button( curMenu.name, systemImage: curMenu.image ) {
//                          }
//                      }
//                  }
               }    // End toolbar  
       }    // End vStack
       .frame( height: 500 )
       .frame( width: 800 )
   }    //  End View

   private func selectTool() {
       print(" in selectTool ")
   }
}

#Preview {
    ContentView()
}
1

There are 1 best solutions below

5
NRitH On

Instead of a for loop, use ForEach:

ForEach(myMenu, id: \.name) { (curMenu) in
    Button(curMenu.name, systemImage: curMenu.image)
}

If the items in the array passed to ForEach conform to Identifiable, you can skip the id: argument. If they don't, you have to pass in the name of a property that ForEach can use as a unique identifier. (I just guessed that the name field is what you want here.)