Showing Selection with MenuButton

I want to create a drop-down menu with years like the following.

Code Block
import SwiftUI
struct ContentView: View {
@State var menuLabel = "2020"
var body: some View {
MenuButton(menuLabel) {
Button("2020") {
menuLabel = "2020"
}
Button("2021") {
menuLabel = "2021"
}
Button("2022") {
menuLabel = "2022"
}
}
.frame(width: 68.0)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}


But that's tedious. So if I would rather do it with ForEach.

Code Block
import SwiftUI
struct ContentView: View {
@State var menuLabel = "2020"
var body: some View {
MenuButton(menuLabel) {
ForEach((2020...2030), id: \.self) {
Button(String($0)) {
menuLabel = String($0)
}
}
}
.frame(width: 68.0)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}


And I will get an error unless I comment out

Code Block
menuLabel = String($0)


It says

Contextual closure type '() -> Void' expects 0 arguments, but 1 was used in closure body

I don't know what it means. So what does it mean, and how can I set the selection to the title of MenuButton, anyway? Thank you.


Answered by OOPer in 652248022

what does it mean

The action closure passed to Button must not have an argument.
But the code you have written:
Code Block
Button(String($0)) {
menuLabel = String($0) //<- This `$0` is an argument of the inner closure, and not the same as `$0` in `Button(String($0))`
}

You are passing a single argument closure to Button.

how can I set the selection to the title of MenuButton

You may need to clarify that $0 is not an argument for the inner closure:
Code Block
struct ContentView: View {
@State var menuLabel = "2020"
var body: some View {
MenuButton(menuLabel) {
ForEach((2020...2030), id: \.self) {
year in //<- explicitly declare the argument for the outer closure
Button(String(year)) {
menuLabel = String(year)
}
}
}
.frame(width: 68.0)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}


Accepted Answer

what does it mean

The action closure passed to Button must not have an argument.
But the code you have written:
Code Block
Button(String($0)) {
menuLabel = String($0) //<- This `$0` is an argument of the inner closure, and not the same as `$0` in `Button(String($0))`
}

You are passing a single argument closure to Button.

how can I set the selection to the title of MenuButton

You may need to clarify that $0 is not an argument for the inner closure:
Code Block
struct ContentView: View {
@State var menuLabel = "2020"
var body: some View {
MenuButton(menuLabel) {
ForEach((2020...2030), id: \.self) {
year in //<- explicitly declare the argument for the outer closure
Button(String(year)) {
menuLabel = String(year)
}
}
}
.frame(width: 68.0)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}


Thank you, again, OOPer. That's an odd closure expression, which I have never seen in Swift.
Showing Selection with MenuButton
 
 
Q