Beginner’s Guide to Event Kit in Swift – Requesting Permission

Updated on October 26, 2016 – Swift 3.0

EventKit provides a set of classes for accessing and manipulating a user’s calendar events and reminders. In the tutorial that follows, my goal is to walk you through the first steps of setting up an app that utilizes EventKit. I will demonstrate how to request permission to the user’s calendar and show a couple of examples for how to handle the user’s response (for when they grant access, or deny it).

Note: Code in the main article below is written in Swift 3.0, but code examples for Swift 2.3 are found in the example project.

Example scenario

Let’s start by proposing a basic scenario to serve as this tutorial’s example.

Suppose that we’re building an app that, for now, has a single View Controller. We’d like this View Controller to display a list of calendars if the user grants us permission to do so. If they deny permission, we’d like to show a message to them that indicates that our app can’t function without this permission, and we’ll allow them to click a button to grant us permission in the Settings of their device.

I’ve created such an app as an example – jump over to GitHub to grab the code and explore. Read on for an explanation of some of the finer points of the setup and code.

Resources

Storyboard setup

One of the first things you’ll deal with in EventKit is the need to set yourself up with a UI to handle the different responses that the user can give you on that first application launch when you ask, “Can we access your calendar?”. We’ll get to the particulars of how request that permission shortly. But first, let’s dissect how we might arrange a Storyboard with some views that do the right thing for a given response to that permission prompt.

The user can either grant permission, or deny permission to interact with their calendar or reminders. We need to be prepared for either scenario.

Tableview for the calendar list for when access is granted

I’m feeling optimistic today, so let’s begin with the case where the user grants us permission to their calendar from the get-go.

When the user grants us permission, we’d like to list out their calendars inside a table view. We’ll worry with setting up the data source later in the tutorial. For now, we’ll drag over a table view from the Utilities pane.

To get the table view to fill the whole screen, I do a couple of things. Usually, when you drag one out from the Utilities pane, the table view will fill the whole scene in the Storyboard. From that layout, I drag the top edge down until it “snaps” to the line where I’d expect the bottom of the status bar to be positioned. Then I set the following constraints:

  • Center X
  • Center Y
  • Equal width to Superview
  • Top space to Top Layout Guide for height.

I’ve created a short screencast on setting up a table view if you’d like a complete walkthrough:

Here’s a detailed view of the constraints, along with a visual of what the Storyboard Scene looks like with the table view installed:
Detailed view of constraints

Table view in Storyboard

As a final note, I’ve set the hidden property of the table view to true in the Storyboard. I’ll toggle the table’s visibility based on the user’s granting or denying of the calendar access later, but I thought it was worth pointing out that the initial state of my table view in the example is hidden.

“Need permission” view for when access is denied

There will be times when a user denies access to the calendar before realizing that doing so essentially stops all the functionality provided by your app. If your entire app, or even just a portion of it requires access to function, you need a way to inform the user of this, and provide them a way to navigate to settings and grant access manually if possible.

The way I did this in the sample project was to organize a new View onto the Storyboard Scene which contains a label with some instructions, and a button that takes the user to the Settings page for our app when they tap on it.

Once again, some constraints are involved in getting things to appear correctly at run-time. I won’t go into the details of this here, since it’s likely that every implementation of this will be slightly different.

One thing I will point out though, is that the View’s alpha has been set to 0 so that I can perform a nice fade in transition if the user denies access. Here’s a look at the Scene with the invisible “NeedPermissionsView” installed:

Need permission view

The role of the Event Store

At the heart of EventKit is the EKEventStore. EKEventStore is the central “thing”. Creating an instance of EKEventStore provides developers with an API for performing various read/write operations on the user’s calendars and reminder lists.

A View Controller that interacts with the calendar should hold a reference to an EKEventStore instance. It’s easy to create one – here’s an example:

Checking for calendar authorization

Once we have a reference to an EKEventStore instance, we can use it to do things like check whether or not the user has granted us permission to use their calendar. From there, we can make decisions about whether or not we need to request permission, and subsequently figure out which view to show (the table view or the need permission view).

Where we check for calendar authorization is important. My recommendation is to check each time the view appears (ie, in viewWillAppear(), because it’s completely possible that the user could grant access at first, switch to settings, and deny access. Our app would need to respond appropriately.

In the example project provided with this article, I’ve created a function named checkCalendarAuthorizationStatus(). Here a peek at what it does:

The key function here is EKEventStore's authorizationStatus(for:) function. Passing in EKEntityType.event is what corresponds to the user’s calendar. If we wanted to check for access to their reminders, we’d use EKEntityTypeReminder.

The possible EKAuthorizationStatus enumeration values are simply switched over – the logic to be performed is encapsulated in separate functions for ease of readability.

Let’s step through each of those functions one by one…

Update Info.plist for iOS 10 support

Apple now requires us to have a key/value pair in Info.plist that provides a description to the user as to why our apps need access to their calendar.

To set this value, open your Info.plist file, and add a new key for “Privacy – Calendars Usage Description”:
Info.plist Calendar Usage Description

The value that you provide for this plist key ends up being displayed in the alert that’s displayed when you request access.

Requesting access to calendars

As the title of this tutorial suggests, all things start here. Whenever our application loads and we call authorizationStatus(for:), the status that will be returned is notDetermined. It’s at this point that we’d like to request access to the calendar.

To do so, let’s dissect the requestAccessToCalendar function:

Our EKEventStore instance provides a function called requestAccess(to:). Once again, passing in EKEntityType.event is what signals that we’re requesting access to the calendar. The rest of the interesting parts are found in the completion closure that we provide.

There are three main things to note with this portion of the implementation:

  1. The two parameters that are passed in to the closure is a Bool indicating access was granted (true) or denied (false). The second is an NSError.
  2. We need to call dispatch_async() and indicate that we want to jump back over to the main queue to execute our UI refreshes.
  3. self.needPermissionView.fadeIn() utilizes a UIView extension from my post, Fade In / Out Animations as Class Extensions in Swift.

Access granted! Load calendars and refresh table view

When access is granted, we can call the eventStore instance’s calendarsForEntityType function and pass it EKEntityType.event to grab an array of the user’s calendars to display in our table view. Here’s a look:

Access denied – Show needs permission view

When access is denied, we need to unveil the “Needs Permission View” we created in our Storyboard Scene.

Recall that in that view, there’s a button to direct the user to the Settings page for our app so that they can easily grant access to the calendar from there. That button is wired up to an IBAction. Here’s an example implementation of that IBAction:

Wrapping up

That pretty much completes the setup process for working with Event Kit! The remaining cases for the checkCalendarAuthorizationStatus() function simply re-use the functions I just dissected when exploring the requesting permission process.

I encourage you to head over to GitHub and dive into the code for yourself as you get started with utilizing Event Kit in your app!

  • Great tutorials! Thanks Andrew for the help! One question, I’m getting an error straight out of the gate – Use of unresolved identifier ‘EKEntityTypeEvent’

    Any ideas?

  • Kymer

    Hey Andrew, awesome tutorial! It was very useful and easy to follow, great work.

    Could you perhaps elaborate on the importance of dispatch_async() in the completion closure? Say, I want to load another view depending if access was granted or denied, does that need to happen in a dispatch_async block as well?

    • Andrew Bancroft

      Hey Kymer!

      Let me see if I can think on it and improve the post with some clarifying comments on dispatch_async(). I’ll reply here again once I’ve update things. Thank you for your question!

      • Kymer

        Hey Andrew, thanks for the quick reply!

        I have been experimenting a bit, and I noticed whenever I tried to load a new view (with a custom function in my AppDelegate) it took quite a while for the new view to appear (like up to 8 seconds sometimes). I also got this warning in the output:

        “This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.”

        So I wrapped my view load code in the dispatch_async block and it solved those issues. I have a vague understanding of why it’s needed, and I will definitely look into it more deeply. But your post was the first time I actually came across the dispatch_async code and its importance, so if you do find a way to elaborate on it in a concise manner that’d definitely help out newbies such as me 🙂

  • James Hartley

    Any updates for iOS 9? I am getting errors for the UIAlert saying that it needs to be UIAlertController now, but i don’t know exactly what to put.

    • Andrew Bancroft

      Hey James!

      Yes – I am currently working through much of my blog content to update for Xcode 7, Swift 2, and iOS 9 where appropriate. Since you’ve asked about this particular post, I’ll bump it up in my list of things to revise. Thanks for bringing this to my attention!

    • Andrew Bancroft

      This post’s code snippets were updated today to reflect the Swift 2.0 / iOS 9 changes made in the GitHub example. Let me know if you notice anything else that’s not working well for you, James.

  • Lydia j

    hi andrewcbancroft .Is there possible to add labels and buttons to the calender day view.I mean is possible to customrize calender like create events.Plz reply

  • Pingback: Listing Calendar Events with Event Kit and Swift - Andrew Bancroft()

  • Fernanda Dos Reis

    sorry for my English.

    I performed the project and I am with the following errors after going to the settings:

    _BSMachError: (Os / kern) invalid capability (20)

    _BSMachError: (Os / kern) invalid name (15)

  • Sreejith S

    hai Is it possible to sync calender Repeat and alert To ios calendar ?… plz help me

    • Andrew Bancroft

      It is possible to create reminders and/or events on a user’s calendar (I think that might be what you’re wanting if you want a repeat alert). I’m in the process of writing up additional posts on these topics, so keep a look out soon.

      • Sreejith S

        first of all thanks.. yes i am keep on looking for your updates. Actually i am doing a app which is same as ios calendar. So Repeat and alert should also pass to ios calendar .. i search so many sites for that no more topic about that. 🙂

  • Pingback: Creating Calendar Events with Event Kit and Swift - Andrew Bancroft()

  • I did the tutorial and looked at the code on Github but my Calendars are still not showing up on the View Controller. (Yes, I made sure the dataSource and delegates are connected