How to use EKCalendarChooser in Swift to let user select calendar in iOS
Tags: ios, swift
Published: 2020-03-20 21:16:48

iOS offers great way to work with calendar events and one part is `EKCalendarChooser` from the `Event Kit` framework. As the name suggests, this lets user select calendar.

This controller takes care of displaying all the user’s calendars and even offers pull to refresh to refresh them should the user choose to do so.
In this short guide I am going to show you how to use the `EKCalendarChooser` and what it offers.

![EKCalendarChooser in action](https://dev-to-uploads.s3.amazonaws.com/i/w5881snk2o07rvi3iq9k.png)

The first step is to modify `Info.plist` with usage descriptions for calendar and contacts. You need both because user may have shared calendars which show people's names.

Those keys are `NSCalendarsUsageDescription` and `NSContactsUsageDescription`. Add them to the `Info.plist` in your app and describe why do you need this access.

Now let’s move to the code.

Start by importing `EventKitUI`:

```swift
import EventKitUI
```

The controller needs an instance of `EKEventStore` to work with events, so let's create one at the class level:

```swift
let eventStore = EKEventStore()
```

We first start with method preparations and then tie them together in a method that will react to button tap in our example.

Let’s start with the main stuff and that is creating `EKCalendarChooser` and presenting it:

```swift
func showCalendarChooser() {
        let vc = EKCalendarChooser(selectionStyle: .single, displayStyle: .allCalendars, entityType: .event, eventStore: eventStore)
        // customization
        vc.showsDoneButton = true
        vc.showsCancelButton = true
        
        // dont forget the delegate
        vc.delegate = self
        
        let nvc = UINavigationController(rootViewController: vc)
        
        self.present(nvc, animated: true, completion: nil)
    }
```

Couple things to note. We are wrapping it in the `UINavigationController` so it has nice navigation bar with optional buttons. 

The `selectionStyle` parameter is used to specify whether we want to select single calendar or multiple. The values are `.single` and `.multiple` respectively.

With `.displayStyle` we can either choose all calendars or only the writable ones.

This code won’t compile just yet. Add `EKCalendarChooserDelegate` delegate conformace to the view controller where you plan to let user select calendars.

```swift
extension ViewController: EKCalendarChooserDelegate {
}
```

If you were to try to show the `EKCalendarChooser` right now, you would get nice explanation with lock icon that says that your app does not have permissions to see the calendars. We need to ask first.

![System screen informing us and the user that the app does not have persmission to access calendars](https://dev-to-uploads.s3.amazonaws.com/i/ab5qeq1pq09xwd0pms2v.jpeg)

Let’s add method to request access:

```swift
func requestAccess() {
        eventStore.requestAccess(to: .event) { (granted, error) in
            if granted {
                // may not be called on the main thread..
                DispatchQueue.main.async {
                    self.showCalendarChooser()
                }
            }
        }
    } 
```

The completion block may not be called on the UI (main) thread, so we are using `DispatchQueue.main.async` to fix that.

We are almost done.

```swift
@IBAction func chooseCalendarTapped(_ sender: UIButton) {
        let authStatus = EKEventStore.authorizationStatus(for: .event)
        
        switch authStatus {
        case .authorized:
            showCalendarChooser()
        case .notDetermined:
            requestAccess()
        case .denied:
            // Explain to the user that they did not give permission
            break
        case .restricted:
            break
        @unknown default:
            preconditionFailure("Who knows what the future holds 🤔")
        }
    }
```

We first ask for the current authorization status and based on the result either show the calendar chooser, ask for permissions or do nothing in this example case. The `.restricted` case can happen due to parental controls for example.

Now let’s turn to the `EKCalendarChooserDelegate` and implement the methods.

```swift
func calendarChooserDidFinish(_ calendarChooser: EKCalendarChooser) {
        print(calendarChooser.selectedCalendars)
        dismiss(animated: true, completion: nil)
}
    
func calendarChooserSelectionDidChange(_ calendarChooser: EKCalendarChooser) {
        print("Changed selection")
}
    
func calendarChooserDidCancel(_ calendarChooser: EKCalendarChooser) {
        print("Cancel tapped")
        dismiss(animated: true, completion: nil)
}
```

Since we are presenting the controller modally, we have to `dismiss` it. You can access the `selectedCalendars` property to get instance of `EKCalendar` that the user selected.

The full example is available on [GitHub](https://github.com/nemecek-filip/EKCalendarChooser.Example). Thanks for reading!

{% link https://dev.to/nemecek_f/how-to-use-ekeventeditviewcontroller-in-swift-to-let-user-save-event-to-ios-calendar-d8 %}



[![Scan it - wide banner](https://nemecek.be/media/images/scanItWideBanner.png)](https://apps.apple.com/app/scan-it-scan-and-export-pdf/id1509634112)