SwiftUI: Pickers and Menu. Build a modern native iOS application.

This article will review pickers and menu elements. You will see how to create an interface for your app using tools and APIs provided by SwiftUI. We will cover DatePicker, ColorPicker, and Menu items. It will help you understand how to use these native tools to bring your app to the next level, improve user experience and make it intuitive.

Arkhyp Koshel
7 min readFeb 8, 2023

When developing applications, I try to use native elements. They are always easier to use, and they are always intuitive to the user. Also, it can have hidden functionality, which the user often uses. Significantly when developers rewrote navigation and forgot or removed gestures to go back. I hate it, and I think it is the biggest mistake.
So, native behavior helps make your application’s use simple and understandable. And often, it is 50% of the success of your application.

DatePicker

Let’s start with DatePicker. Imagine that we need to create a registration form with a birth date field. With the old DatePicker, we would have three wheels with the choice of year, month, and day. But for now, it is an ancient and not-so-great way to choose a date. Especially if you need your application runs on multiple systems. Because the new DatePicker is suitable for touch gestures, mouse, and apple pencil pointing.

See how Apple worries about everything so you can focus on your idea and the app’s functionality. 😎

To add basic DatePicker to your form, use the following code. When the user taps or clicks the date text, a calendar will appear from which the user can select a date.

DatePicker("Birth date:",
selection: $date,
displayedComponents: [.date])

We added a basic view of DatePicker. And now, your UI should show the “Birth date:” field with a pre-selected date.

SwiftUI. Basic DatePicker view
SwiftUI. Basic DatePicker view

The first parameter is the title key. It describes the purpose of the field. The second one is the date value being selected and displayed. The last one is display components that the user can view and edit. By default, it also includes hours and minutes.

Now check how cool this is.

SwiftUI. Demo usage of DatePicker
SwiftUI. Demo usage of DatePicker

Let’s see how we can improve our date picker. You also can add a range. It will be an inclusive range of selectable dates. So if we need to add a range, for example, the user should be 18 years old but not older than 100 years, we need to use the following code.

let minDate = Calendar.current.date(byAdding: .year, value: -100, to: Date())!
let maxDate = Calendar.current.date(byAdding: .year, value: -18, to: Date())!
//unwrapped values, just for example. In actual code, it is always better to avoid it.

//... some code here.

DatePicker("Birth date:",
selection: $date,
in: minDate...maxDate,
displayedComponents: [.date])
SwiftUI. DatePicker with added range.

And now you can't select a date out of the range. And now you can’t select a date out of the range. You can customize DatePicker with different default modifiers, like “foregroundColor”, “font”, etc.

You can face a big problem if you try to remove the gray background under the date label. Let me know in the comments if you want me to add a small tutorial on how to do it. 😉

Also, the significant part about DatePicker is that you can choose one of three styles: graphical, wheel, and compact. Or you can select automatic, which is by default. The graphical style is practical when you want to allow browsing through days in a calendar or when the look of a clock face is appropriate.
The wheel style displays each component as columns in a scrollable wheel.
The compact style displays the components in a compact, textual format. The picture below shows all styles.

SwiftUI. DatePicker styles: 1) graphical; 2) wheel; 3) compact.
SwiftUI. DatePicker styles: 1) graphical; 2) wheel; 3) compact.

To add a style use the datePickerStyle modifier and pass desired style value:

DatePicker("Birth date:", selection: $date, in: minDate...maxDate, displayedComponents: [.date])
.datePickerStyle(.graphical)

Use these styles wisely because each style can be better for current needs. For example, if you use the entire screen to select only one date, the best solution is to use the graphical style. But if you have a form with many fields, it is better to use the compact style. These styles give you more flexibility and variety in how to use DatePicker. But still, it is far from perfect. You can not customize it and change everything.

You also can face a problem that you must specify the date value. You can not make it optional by default. So if you want to know how, please, follow me and leave a comment. I will publish how to do it properly.

ColorPicker

So, we are going to see how to use ColorPicker. Only recently, Apple added this element. I was working on a smart house application and had to implement my realization of DatePicker. But now you can use DatePicker provided by SwiftUI in a few code lines. To add a color picker add this code below after the DatePicker view mentioned above or create a new View to work with.

ColorPicker(selection: $selectedColor, supportsOpacity: true) {
Text("Favorite color: ")
}

It is super easy, and now your user can choose any color.

SwiftUI. ColorPicker
SwiftUI. ColorPicker

ColorPicker shows selected and displays the large color picker. You also can remove or add an opacity option. By default, it is true. Try to change the supportsOpacity parameter to false and test it. You will see that the opacity section is gone.

One good thing about ColorPicker is that you can customize the title because the last parameter is a closure which returns a view that describes the use of the selected color. In the following code snippet, we moved our title to VerticalStack and added a subtitle with color-chosen components. But here you can go further.

ColorPicker(selection: $selectedColor, supportsOpacity: false) {
VStack(alignment: .leading) {
Text("Favorite color: ")
Text("\tR: \(selectedColor.components.red) G: \(selectedColor.components.green) B: \(selectedColor.components.blue)")
.font(.caption)
.foregroundColor(selectedColor)
}
}

Beware, components property is manually added through extension. Add your realization of this property or replace this part of the code.

SwiftUI. ColorPicker with the customized title.
SwiftUI. ColorPicker with the customized title.

ColorPicker was among the most expected, especially for those who have long been developing native applications. Take your time to play and see how you can customize the title and improve your app user experience.

Menu Button

It is time to improve your UI with menu buttons. With this UI control, you don’t need to place all buttons on a screen view. You can hide it under one button and show him a list with action buttons where the user can choose any action. Going further, you can even use the menu inside the other menu. I will show you how to do it.

To add menu buttons, add the following lines where you want to add the menu to your code.

Menu {
Button(action: duplicate) {
Label("Duplicate item", systemImage: "doc.on.doc")
}
Button("Edit item", action: edit)
Menu {
Button("Open in Preview", action: openPreview)
Button("Save as PDF", action: save)
} label: {
Label("PDF", systemImage: "doc")
}
Button(role: .destructive, action: delete) {
Label("Delete", systemImage: "trash")
}
.foregroundColor(.red)
} label: {
Image(systemName: "square.and.pencil")
}

// Actions
/*
func duplicate() { }
func edit() { }
func openPreview() { }
func save() { }
func delete() { }
*/

As a result, you will see a popup menu with defined buttons. In this example, I used different buttons to show you how you can customize it.

Please download the SF Symbols app to browse all available system names.

SwiftUI. Menu buttons in action.

And now, it is time to figure out how to customize the Menu button. To do it, you will need to create another struct. I will name it MyMenuStyle, and this struct has to implement the MenuStyle protocol.

struct MyMenuStyle: MenuStyle {
func makeBody(configuration: Configuration) -> some View {
Menu(configuration)
.padding(6)
.background(.black, in: RoundedRectangle(cornerRadius: 4, style: .circular))
.foregroundColor(.white)
}
}

Just call on your Menu item menySthyle function.

Menu {
// previous code here
} label: {
Image(systemName: "square.and.pencil")
}
.menuStyle(MyMenuStyle())

Also, let’s improve our style to use it properly. Extend the MenuStyle protocol with the following code.

extension MenuStyle where Self == MyMenuStyle {
static var myMenuStyle: MyMenuStyle { .init() }
}

After this minor improvement, you can use your style like:

Menu {
// previous code here
} label: {
Image(systemName: "square.and.pencil")
}
.menuStyle(.myMenuStyle)

The final result should be

SwiftUI. Menu button with custom style.
SwiftUI. Menu button with custom style.

Take your time to play with different configurations to understand better how it works.

SwiftUI is a robust UI framework, easy to use, and you can quickly create any interface. As always, there’s plenty to tell and show. If you appreciate this post, here are three things you can do to support my work:

Thank you for taking the time to read my story and for your support. If you enjoyed this article, please clap it to let me know. I will be sharing more stories in the future, so be sure to follow me to stay updated. Your feedback and support are greatly appreciated!
Follow Me: Twitter | LinkedIn

Next time I will show you how to ContextMenu as in the image below and show how to asynchronously provide menu items. Thanks for reading.

SwiftUI. Context Menu
SwiftUI. Context Menu

--

--

Arkhyp Koshel
Arkhyp Koshel

Written by Arkhyp Koshel

iOS and macOS developer. Passionated about technology, personal growth, and programming. Range of experiance the auto industry and banking.

Responses (3)