Picker
A control for selecting from a set of mutually exclusive values.
Declaration
struct Picker<Label, SelectionValue, Content> where Label : View, SelectionValue : Hashable, Content : ViewMentioned in
Overview
You create a picker by providing a selection binding, a label, and the content for the picker to display. Set the selection parameter to a bound property that provides the value to display as the current selection. Set the label to a view that visually describes the purpose of selecting content in the picker, and then provide the content for the picker to display.
For example, consider an enumeration of ice cream flavors and a State variable to hold the selected flavor:
enum Flavor: String, CaseIterable, Identifiable {
case chocolate, vanilla, strawberry
var id: Self { self }
}
@State private var selectedFlavor: Flavor = .chocolateYou can create a picker to select among the values by providing a label, a binding to the current selection, and a collection of views for the picker’s content. Append a tag to each of these content views using the View/tag(_:) view modifier so that the type of each selection matches the type of the bound state variable:
List {
Picker("Flavor", selection: $selectedFlavor) {
Text("Chocolate").tag(Flavor.chocolate)
Text("Vanilla").tag(Flavor.vanilla)
Text("Strawberry").tag(Flavor.strawberry)
}
}If you provide a string label for the picker, as the example above does, the picker uses it to initialize a Text view as a label. Alternatively, you can use the init(selection:content:label:) initializer to compose the label from other views. The exact appearance of the picker depends on the context. If you use a picker in a List in iOS, it appears in a row with the label and selected value, and a chevron to indicate that you can tap the row to select a new value:
[Image]
For cases where adding a subtitle to the label is desired, use a view builder that creates multiple Text views where the first text represents the title and the second text represents the subtitle:
List {
Picker(selection: $selectedFlavor) {
Text("Chocolate").tag(Flavor.chocolate)
Text("Vanilla").tag(Flavor.vanilla)
Text("Strawberry").tag(Flavor.strawberry)
} label: {
Text("Flavor")
Text("Choose your favorite flavor")
}
}Iterating over a picker’s options
To provide selection values for the Picker without explicitly listing each option, you can create the picker with a ForEach:
Picker("Flavor", selection: $selectedFlavor) {
ForEach(Flavor.allCases) { flavor in
Text(flavor.rawValue.capitalized)
}
}ForEach automatically assigns a tag to the selection views using each option’s id. This is possible because Flavor conforms to the Identifiable protocol.
The example above relies on the fact that Flavor defines the type of its id parameter to exactly match the selection type. If that’s not the case, you need to override the tag. For example, consider a Topping type and a suggested topping for each flavor:
enum Topping: String, CaseIterable, Identifiable {
case nuts, cookies, blueberries
var id: Self { self }
}
extension Flavor {
var suggestedTopping: Topping {
switch self {
case .chocolate: return .nuts
case .vanilla: return .cookies
case .strawberry: return .blueberries
}
}
}
@State private var suggestedTopping: Topping = .nutsThe following example shows a picker that’s bound to a Topping type, while the options are all Flavor instances. Each option uses the tag modifier to associate the suggested topping with the flavor it displays:
List {
Picker("Flavor", selection: $suggestedTopping) {
ForEach(Flavor.allCases) { flavor in
Text(flavor.rawValue.capitalized)
.tag(flavor.suggestedTopping)
}
}
HStack {
Text("Suggested Topping")
Spacer()
Text(suggestedTopping.rawValue.capitalized)
.foregroundStyle(.secondary)
}
}When the user selects chocolate, the picker sets suggestedTopping to the value in the associated tag:
[Image]
Another example of when the views in a picker’s ForEach need an explicit tag modifier is when you select over the cases of an enumeration that conforms to the Identifiable protocol by using anything besides Self as the id parameter type. For example, a string enumeration might use the case’s rawValue string as the id. That identifier type doesn’t match the selection type, which is the type of the enumeration itself.
Styling pickers
You can customize the appearance and interaction of pickers using styles that conform to the PickerStyle protocol, like segmented or menu. To set a specific style for all picker instances within a view, use the pickerStyle(_:) modifier. The following example applies the segmented style to two pickers that independently select a flavor and a topping:
VStack {
Picker("Flavor", selection: $selectedFlavor) {
ForEach(Flavor.allCases) { flavor in
Text(flavor.rawValue.capitalized)
}
}
Picker("Topping", selection: $selectedTopping) {
ForEach(Topping.allCases) { topping in
Text(topping.rawValue.capitalized)
}
}
}
.pickerStyle(.segmented)[Image]
Topics
Creating a picker
Creating a picker for a collection
Creating a picker with an image label
init(_:image:selection:content:)init(_:image:sources:selection:content:)init(_:systemImage:selection:content:)init(_:systemImage:sources:selection:content:)
Deprecated initializers
Initializers
init(_:image:selection:content:currentValueLabel:)init(_:image:sources:selection:content:currentValueLabel:)init(_:selection:content:currentValueLabel:)init(_:sources:selection:content:currentValueLabel:)init(_:systemImage:selection:content:currentValueLabel:)init(_:systemImage:sources:selection:content:currentValueLabel:)init(selection:content:label:currentValueLabel:)init(sources:selection:content:label:currentValueLabel:)