Pickers

Last updated on 18 Oct 2024.

Written by Jia Chen.

Pickers

Last updated on 18 Oct 2024.

Written by Jia Chen.

Pickers

Last updated on 18 Oct 2024.

Written by Jia Chen.

Scroll Down

On this page

Video

On this page

Creating a Picker

To create a Picker, you will need to supply it with 3 things, a Selection—a Binding boolean to indicate the user's selection, a Label—a companion label to describe the picker's purpose, and the Options—a series of views for each option.

struct ContentView: View {
    @State private var selection = 1
    
    var body: some View {
        Picker("Subscription", selection: $selection) {
            Text("Free Tier")
                .tag(1)
            Text("Pro Tier")
                .tag(2)
            Text("Pro Max Tier")
                .tag(3)
        }
    }
}

The appearance differs when inside a List or Form. In a List or Form, the label's value is visible. The label's content, while not visible when not present when outside of a List or Form, is still important as it is used as part of the assistive technologies.

struct ContentView: View {
    @State private var selection = 1
    
    var body: some View {
        Form {
            Picker("Subscription", selection: $selection) {
                Text("Free Tier")
                    .tag(1)
                Text("Pro Tier")
                    .tag(2)
                Text("Pro Max Tier")
                    .tag(3)
            }
        }
    }
}

Basic Pickers

Text Labels

Each picker option has to be supplied with a tag. When the option is selected, the tag value gets set to the Binding value in the selection parameter.

@State private var selection = 1
Picker("Subscription", selection: $selection) {
    Text("Free Tier")
        .tag(1)
    Text("Pro Tier")
        .tag(2)
    Text("Pro Max Tier")
        .tag(3)
}

By default, the label is hidden. In a Form or List, the Picker's label shows up.

Text and Image Labels

You can add an image or an SF Symbol to your labels. This will only appear when inside a Form or a List. Outside of a Form or List, by default, the icon or image will be hidden.

Picker("Subscription", systemImage: "sparkles", selection: $selection) {
    Text("Free Tier")
        .tag(1)
    Text("Pro Tier")
        .tag(2)
    Text("Pro Max Tier")
        .tag(3)
}

Custom Labels

You can pass in a label closure after the Picker's options to create a custom label.

Picker(selection: $selection) {
    Text("Free Tier")
        .tag(1)
    Text("Pro Tier")
        .tag(2)
    Text("Pro Max Tier")
        .tag(3)
} label: {
    HStack {
        Image(systemName: "dollarsign.circle")
        Image(systemName: "arrow.forward")
        Image(systemName: "face.smiling")
    }
}

Picker Options

Using Enumerations

You can use an enumeration to set up your Picker. This is a far more elegant approach as you can use the cases in the enumeration as picker options.

To achieve this, create an enumeration. This enumeration needs to either have a Raw Value, or conform directly to the Hashable protocol. You can then supply the enumeration value as the tag.

enum SubscriptionTier: String {
    case free
    case pro
    case proMax
}
struct ContentView: View {
    @State private var subscription: SubscriptionTier = .free
    
    var body: some View {
        Form {
            Picker("Subscription", selection: $subscription) {
                Text("Free Tier")
                    .tag(SubscriptionTier.free)
                Text("Pro Tier")
                    .tag(SubscriptionTier.pro)
                Text("Pro Max Tier")
                    .tag(SubscriptionTier.proMax)
            }
        }
    }
}

Using ForEach

A ForEach can also be used to create the options.

In the example below, the cases in the enumeration can be given an explicit raw value corresponding to each option's title. Conforming to CaseIterable allows you to access all cases of the enumeration with the allCases static property.

A ForEach can then be used to iterate over all the cases and display them as options in the Picker.

enum SubscriptionTier: String, CaseIterable {
    case free = "Free Tier"
    case pro = "Pro Tier"
    case proMax = "Pro Max Tier"
}
Picker("Subscription", selection: $subscription) {
    ForEach(SubscriptionTier.allCases, id: \.self) { tier in
        Text(tier.rawValue)
            .tag(tier)
    }
}

Styling Pickers

Like other views, applying picker style is as simple as using the .pickerStyle modifier on the picker or a view containing a picker.

struct ContentView: View {
    @State private var subscription: SubscriptionTier = .free
    
    var body: some View {
        Form {
            Picker("Subscription", selection: $subscription) {
                ForEach(SubscriptionTier.allCases, id: \.self) { tier in
                    Text(tier.rawValue)
                        .tag(tier)
                }
            }
            .pickerStyle(.inline)
        }
    }
}

Individual Style Options

Inline

.pickerStyle(.inline)

Standalone

In Form / List

Menu

.pickerStyle(.menu)

Standalone

In Form / List

Navigation Link

When using the navigation link picker style, the Picker must be within a Navigation View, like a NavigationStack or NavigationSplitView.

.pickerStyle(.navigationLink)

Standalone

In Form / List

Palette

.pickerStyle(.palette)

Standalone

In Form / List

Segmented

.pickerStyle(.segmented)

Standalone

In Form / List

Wheel

.pickerStyle(.wheel)

Standalone

In Form / List

Cascading Styles

With the pickerStyle modifier, picker styles will cascade down. This allows you to attach the pickerStyle to any parent / ancestor view to have the style applied to all child views.

This can be particularly useful when dealing with forms and keeping the picker styles similar.

Form {
    Section {
        Picker(...) { ... }
        Picker(...) { ... }
    }
}
.pickerStyle(.menu)

Pickers with Collections (work in progress)


Custom Current Value Labels (work in progress)


© 2024 Tinkertanker Pte Ltd / Swift Accelerator. All rights reserved.

© 2024 Tinkertanker Pte Ltd / Swift Accelerator. All rights reserved.

© 2024 Tinkertanker Pte Ltd / Swift Accelerator. All rights reserved.