How to create new calendar using EventKit in Swift

Apart from reminders and events, EventKit framework also gives you the power to create new calendars for users. Let's see how.

In the previous posts I already wrote about creating events andreminders using EventKit. Turns out you can create a new calendar too.

The process does not involve much. Basically "just" creating an instance of EKCalendar , configuring it and saving. But there is one big caveat called EKSource.

This is required otherwise the calendar can't be saved. We can use an instance of EKEventStore to query all available sources but figuring which one to use is tricky.

It also depends if you want for your user to pick this source. In this case you should present it as choosing an account which it ultimate represents and you can use title property as user readable identifier. This can be something like "iCloud", "Gmail" and others.

Or you can try picking the best one which I have done for my example EventKit project:

func bestPossibleEKSource() -> EKSource? {
        let `default` = eventStore.defaultCalendarForNewEvents?.source
        let iCloud = eventStore.sources.first(where: { $0.title == "iCloud" }) // this is fragile, user can rename the source
        let local = eventStore.sources.first(where: { $0.sourceType == .local })

        return `default` ?? iCloud ?? local
}

I think for an example this works fine. I first try to get source from the default calendar, if that fails we can try finding one named "iCloud" but user can rename them, and lastly try local.

The available sourceTypes are available in official docs. The calDAV could be promising:

Represents a CalDAV or iCloud source.

As I said. It depends on what you are building. If it is fully featured calendar app then it makes sense to let user pick the source.

Creating calendar

Finally. With EKSource out of the way, let's create a new calendar:

func createNewCalendar(withName name: String) {
        let calendar = EKCalendar(for: .event, eventStore: eventStore)
        calendar.title = name
        calendar.cgColor = UIColor.purple.cgColor

        guard let source = bestPossibleEKSource() else {
            return // source is required, otherwise calendar cannot be saved
        }
        calendar.source = source   
        try! eventStore.saveCalendar(calendar, commit: true)
}

The full code is available in the example project on GitHub. You can also check out my other EventKit articles.

Uses: Xcode 11 & Swift 5