How to use UICalendarView in iOS

Look at setting up the proper calendar view with selections and customizations.

Published: June 16, 2022
See books

Since iOS 16, we can use a dedicated calendar view to let users select dates in a way that offers more control than with the standard UIDatePicker.

UICaledarView looks similar to the modern UIDatePicker introduced with iOS 14. This blog post is intended to get you started quickly.

We will look at:

  • How to start using the calendar view
  • How to select a single date
  • How to select multiple dates
  • How to disable selection for specific dates
  • How to decorate days in the calendar with images, colors, or custom views

Basic setup

UICalendarView is a standard UIKit view, so we can use it freely. Note that it is not available in the Interface Builder library. So if you are using Storyboards, you will need to set up a container view for it and initialize it in code.

Start by creating an instance:

let calendarView = UICalendarView()

And then configure it for your needs:

let gregorianCalendar = Calendar(identifier: .gregorian)
calendarView.calendar = gregorianCalendar

It defaults to Calendar.current but we can set it always to be gregorian calendar for greater control.

Further, you can customize locale, timeZone, and fontDesign where the .rounded option looks pretty nice.

And of course, the tintColor to change the default blue look.

calendarView.tintColor = .systemMint

You can also restrict the available dates with the availableDateRange property. This can be easily created using two dates, like this:

calendarView.availableDateRange = DateInterval(start: .now, end: .distantFuture)

And the result:

UICalendarView basic example UIKit Swift

Selecting single date

Selection in the UICalendarView is handled via selectionBehavior property, and each has a dedicated delegate.

To let user select single date, we first setup the selection behavior:

let selection = UICalendarSelectionSingleDate(delegate: self)
calendarView.selectionBehavior = selection

And implement the delegate requirements. Only one method is required.

extension ViewController: UICalendarSelectionSingleDateDelegate {
    func dateSelection(_ selection: UICalendarSelectionSingleDate, didSelectDate dateComponents: DateComponents?) {
        print(dateComponents)
    }
}

And with this, you have a calendar view where the user can select a single date.

UICalendarView selection tutorial Swift

How to disable selection of certain dates

If you want to prevent the user from ever selecting certain dates, for example when tickets for given day are sold out, there is the second and last method from the UICalendarSelectionSingleDateDelegate:

func dateSelection(_ selection: UICalendarSelectionSingleDate, canSelectDate dateComponents: DateComponents?) -> Bool {
    return true
}

If you return false for any of the dateComponents parameter, the day in the calendar view is greyed out and cannot be selected.

This gives you more flexibility than the limited date range with availableDateRange.

Selecting multiple dates

Multi-select works similarly to a single selection, we need to implement different delegate and a couple of methods.

Start by configuring the selection:

let multiSelect = UICalendarSelectionMultiDate(delegate: self)
calendarView.selectionBehavior = multiSelect

And next, we need this delegate: UICalendarSelectionMultiDateDelegate

It requires two methods - we have to handle new selection and deselection.

extension ViewController: UICalendarSelectionMultiDateDelegate {
    func multiDateSelection(_ selection: UICalendarSelectionMultiDate, didSelectDate dateComponents: DateComponents) {

    }

    func multiDateSelection(_ selection: UICalendarSelectionMultiDate, didDeselectDate dateComponents: DateComponents) {

    }
}

And once again, we can also limit selection and also deselection. If you wanted to prevent the user from deselecting certain dates.

func multiDateSelection(_ selection: UICalendarSelectionMultiDate, canSelectDate dateComponents: DateComponents) -> Bool {
    guard let day = dateComponents.day else {
        return false
    }
    return day.isMultiple(of: 2)
}

func multiDateSelection(_ selection: UICalendarSelectionMultiDate, canDeselectDate dateComponents: DateComponents) -> Bool {
        return dateComponents.day != 14
}

My example implementation allows the selection of even days and doesn’t allow the user to deselect the 14th day.

Programmatic selection

Chances are, you would want to pre-select some dates for the user. UICalendarView has got you covered. Or instead, the available selections do, since you won’t find any setSelectedDate on the UICalendarView.

These methods are available on the UICalendarSelectionSingleDate and UICalendarSelectionMultiDate.

For the first one you can call setSelected with a single instance of DateComponents and for the multi-select, there is setSelectedDates. Both allow you to animate this optionally.

To scroll to particular dates, you can also use setVisibleDateComponents on the UICalendarView.

Showing custom information in calendar view

And lastly, let’s look at how we can show additional information in the calendar view. Suppose you are making an app to book hotel stays. For example, you could use an indicator to show which dates offer the best price. Or something similar.

And of course, the classic example shows which days have any events.

To show custom decorations - the official term for these - you need to implement the UICalendarViewDelegate protocol.

calendarView.delegate = self

And it has a single method that can optionally return decoration of type UICalendarView.Decoration.

This can be a simple colored dot with a specified size, UIImage (SF Symbols work great here) or a completely custom UIView subclass.

extension ViewController: UICalendarViewDelegate {
    func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? {
    guard let day = dateComponents.day else {
        return nil
    }

    if !day.isMultiple(of: 2) {
        return UICalendarView.Decoration.default(color: .systemGreen, size: .large)
    }

    return nil
    }
}

I am once again using super simple rules to show the decorations. In an actual project, you would consult your data source and either show decorations or not based on some condition.

UICalendarView custom decoration how to swift

What about selecting date ranges?

I mentioned as an example an app that would let users select dates for upcoming hotel stays. In such cases, you would typically select the start and end dates which the UICalendarView does not really support out of the box.

I guess the reason might be we already have UIDatePicker, but I plan to hopefully explore using this new component for date ranges soon and write about it.

What about SwiftUI?

Unfortunately, this component does not have SwiftUI counterpart, so you will have to wrap it in the UIViewRepresentable.

Are you interested in more “calendar stuff”? I have entire series dedicated to EventKit framework, which lets developers read events from the iOS calendar and create a new one, work with reminders, and more.

Filip Němeček profile photo

WRITTEN BY

Filip Němeček @nemecek_f@iosdev.space

iOS blogger and developer with interest in Python/Django. Want to see most recent projects? 👀

iOS blogger and developer with interest in Python/Django. Want to see most recent projects? 👀