DatePicker in SwiftUI 

DevTechie Inc
May 28, 2022
DatePicker is a control that allows users to select a calendar date and time. View binds to a Date instance.

Let’s start with a simple example for DatePicker. We will create a State property of type Date to bind it with DatePicker as shown below:

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        DatePicker("Pick a date and time", selection: $date)
            .padding()
    }
}
DatePicker shows date and time values in the view, when you tap on date or time sections, the pop-up is presented to make a selection.

Display Components
For DatePicker View, we have the option to show only date or time components as well and it can be done with the help of displayedComponents a parameter which takes a collection of DatePickerComponents. We can choose to show .date, .hourAndMinutes at the same time or one of them.

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        DatePicker("Pick a date", selection: $date, displayedComponents: [.date])
            .padding()
    }
}
We can change our example to display time view for DatePicker by simply replacing .date with .hourAndMinute

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        DatePicker("Pick a time", selection: $date, displayedComponents: [.hourAndMinute])
            .padding()
    }
}
Date Picker Range
We can limit the DatePicker to specific ranges of dates, allowing date selections only before or, after a certain date, or between two dates.

Let’s update our example to show a date picker that only permits selections starting the current date which will restrict the selection of dates before the current day.

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: Date()...,
            displayedComponents: [.date])
            .padding()
    }
}
Alternatively, we can choose to limit date selection to current date meaning no future date selection is allowed.

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: ...Date(),
            displayedComponents: [.date])
            .padding()
    }
}
We can even allow selection between two dates.

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: Date().addingTimeInterval(-1000000)...Date(),
            displayedComponents: [.date])
            .padding()
    }
}
DateRange can also be created with specific dates in a variable and used in DatePicker view.

struct DatePickerExample: View {
    @State private var date = Date()    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current
        let startComponents = DateComponents(year: 2021, month: 12, day: 15)
        let endComponents = DateComponents(year: 2021, month: 12, day: 30, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
        ...
        calendar.date(from:endComponents)!
    }()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: dateRange,
            displayedComponents: [.date])
            .padding()
    }
}
DatePicker Style
We can style DatePicker using datePickerStyle modifier. There are 4 values to choose from.

.automatic : sets DatePicker style based on system its being rendered.

.compact : sets DatePicker style to compact display which renders date and time views that can be tapped to reveal calendar and time picker.

.graphical : sets DatePicker style to display calendar view.

.wheel : sets DatePicker style to be displayed in selection wheel style.

Let’s look at them one by one.

.automatic DatePicker Style
struct DatePickerExample: View {
    @State private var date = Date()
    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current
        let startComponents = DateComponents(year: 2021, month: 12, day: 15)
        let endComponents = DateComponents(year: 2021, month: 12, day: 30, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
        ...
        calendar.date(from:endComponents)!
    }()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: dateRange,
            displayedComponents: [.date, .hourAndMinute])
            .padding()
            .datePickerStyle(.automatic)
    }
}
.compact DatePickerStyle
struct DatePickerExample: View {
    @State private var date = Date()
    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current
        let startComponents = DateComponents(year: 2021, month: 12, day: 15)
        let endComponents = DateComponents(year: 2021, month: 12, day: 30, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
        ...
        calendar.date(from:endComponents)!
    }()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: dateRange,
            displayedComponents: [.date, .hourAndMinute])
            .padding()
            .datePickerStyle(.compact)
    }
}
Note: .automatic and .compact look same in our case as the style for .automatic is a system pick.

.graphical DatePickerStyle
struct DatePickerExample: View {
    @State private var date = Date()
    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current
        let startComponents = DateComponents(year: 2021, month: 12, day: 15)
        let endComponents = DateComponents(year: 2021, month: 12, day: 30, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
        ...
        calendar.date(from:endComponents)!
    }()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: dateRange,
            displayedComponents: [.date, .hourAndMinute])
            .padding()
            .datePickerStyle(.graphical)
    }
}
.wheel DatePickerStyle
struct DatePickerExample: View {
    @State private var date = Date()
    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current
        let startComponents = DateComponents(year: 2021, month: 12, day: 15)
        let endComponents = DateComponents(year: 2021, month: 12, day: 30, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
        ...
        calendar.date(from:endComponents)!
    }()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: dateRange,
            displayedComponents: [.date, .hourAndMinute])
            .padding()
            .datePickerStyle(.wheel)
    }
}
Background Color for DatePicker
Background modifier for DatePicker works same as it works for any other view in SwiftUI.

We will apply .background modifier with orange color and roundedRectangle shape.

struct DatePickerExample: View {
    @State private var date = Date()
    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current
        let startComponents = DateComponents(year: 2021, month: 12, day: 15)
        let endComponents = DateComponents(year: 2021, month: 12, day: 30, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
        ...
        calendar.date(from:endComponents)!
    }()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: dateRange,
            displayedComponents: [.date, .hourAndMinute])
            .padding()
            .datePickerStyle(.graphical)
            .background(Color.orange.opacity(0.2), in: RoundedRectangle(cornerRadius: 20))
            .padding()
    }
}
Accent Color for DatePicker
DatePicker can be customized further by setting accentColor for the picker. This will make your DatePicker blend well into your app’s theme.

Accent can be set by using .accentColor modifier with DatePicker as shown below:

struct DatePickerExample: View {
    @State private var date = Date()
    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current
        let startComponents = DateComponents(year: 2021, month: 12, day: 15)
        let endComponents = DateComponents(year: 2021, month: 12, day: 30, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
        ...
        calendar.date(from:endComponents)!
    }()
    
    var body: some View {
        DatePicker(
            "Pick a date", 
            selection: $date, 
            in: dateRange,
            displayedComponents: [.date, .hourAndMinute])
            .padding()
            .datePickerStyle(.graphical)
            .padding()
            .accentColor(.orange)
    }
}
Hiding DatePicker Label
DatePicker by default contains a label which is a string but what if you want to provide your own view as a label and not display the default label 🤔

We can set the label as an empty string but that would not solve the problem entirely, let’s try that first.

We will wrap our DatePicker inside a HStack and provide our own Text View, which will serve as a label for the view. We will also set DatePicker label string to be empty.

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        HStack {
            Text("Pick a date")
            DatePicker(
                "", 
                selection: $date, 
                displayedComponents: [.date, .hourAndMinute])
                .padding()
                .datePickerStyle(.compact)
                .padding()
        }
    }
}
Notice that our Text view is pushed out and there is space between Text view and DatePicker.

If we use .labelsHidden modifier then we can hide label completely which will remove the label from DatePicker view hierarchy. To show the difference, we will put two HStack inside a VStack to see the effect.

struct DatePickerExample: View {
    @State private var date = Date()
    
    var body: some View {
        VStack {
            HStack {
                Text("LabelsHidden")
                DatePicker(
                    "", 
                    selection: $date, 
                    displayedComponents: [.date, .hourAndMinute])
                    .padding()
                    .datePickerStyle(.compact)
                    .padding()
                    .labelsHidden()
                    .border(Color.cyan)
            }
            
            HStack {
                Text("Empty Label")
                DatePicker(
                    "", 
                    selection: $date, 
                    displayedComponents: [.date, .hourAndMinute])
                    .padding()
                    .datePickerStyle(.compact)
                    .padding()
                    .border(Color.cyan)
            }
        }.padding()
    }
}

With that, we have reached the end of this article. Thank you once again for reading.