The EventKit framework consists of a range of classes designed specifically to provide access to the calendar database and to facilitate the management of events (EKEventStore
), reminders (EKReminder
) and alarms (EKAlarm
).
EKEventStore
class provides an interface between applications and the underlying calendar database. The calendar database can contain multiple calendars. Each calendar in a database is represented in code in the form of an EKCalendar
object. An EKEventStore
object must request access to the calendar at the point that it is initialized. This request must specify whether access is required for calendar events (.event
) or reminders (.reminder
).EKEvent
and EKReminder
classes respectively.EKAlarm
class is used to configure alarms to alert the user at a specified point in the future.Since this component interacts with system, the first step is to add two permission into Info.plist for your project.
NSCalendarsUsageDescription
like "Allow access to calendar in order to save events".NSContactsUsageDescription
. You need this permission because user may have shared calendars which show people's names.Second, there are two approach to add a new event either via EKEventEditViewController
or just direct to EKEventStore
.
Adding events to the a calendar with a modal
EventKit
provides us with an EKEventEditViewController
which can be presented modally with an event’s pre-filled information so the user can edit some fields of the event before adding it to a calendar.
To add simple event via EKEventEditViewController
you basically need just an instance of EKEvent
and EKEventStore
.
The EKEvent
is the event itself, it has properties like title
, startDate
etc, those will be shown in the controller and subsequently saved to the user's calendar.
Import EventKitUI
like so
import EventKitUI
Start by requesting access
let eventStore = EKEventStore() switch EKEventStore.authorizationStatus(for: .event) { case .denied, .restricted: print("Access denied") case .notDetermined: eventStore.requestAccess(to: .event) { [weak self] (granted, error) in DispatchQueue.main.async { if granted { self!.insertEvent(store: eventStore) } else { print("Access denied") } } } case .authorized: insertEvent(store: eventStore) default: break }
Create the controller object
let eventVC = EKEventEditViewController() eventVC.editViewDelegate = self // don't forget the delegate eventVC.eventStore = EKEventStore()
Next create your EKEvent
instance and use the EKEventStore
instance from eventVC
.
let event = EKEvent(eventStore: eventVC.eventStore) event.title = "My first event!" event.startDate = Date() eventVC.event = event
And show it
present(eventVC, animated: true)
You need the delegate method to close the view controller
func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) { dismiss(animated: true, completion: nil) }
Adding events to the user’s default calendar programmatically
Following is a snippet for inserting a event to default calendar
func insertEvent(store: EKEventStore) { // get list of all calendaers // let calendars = store.calendars(for: .event) let today = Date() let newEvent = EKEvent(eventStore: eventStore) newEvent.calendar = eventStore.defaultCalendarForNewEvents newEvent.title = "My first event!" newEvent.startDate = today newEvent.endDate = Calendar.current.date(byAdding: .day, value: 1, to: today) // set alarm 5 minutes before event let alarm = EKAlarm(relativeOffset: TimeInterval(-60 * 5)) newEvent.addAlarm(alarm) do { try store.save(event, span: .thisEvent) } catch { print("Error saving event in calendar") } } }
Also we can check if a event already exists in the calendar
func checkEventExists(store: EKEventStore, event eventToAdd: EKEvent) -> Bool { let predicate = store.predicateForEvents(withStart: eventToAdd.startDate, end: eventToAdd.endDate, calendars: nil) let existingEvents = eventStore.events(matching: predicate) let exists = existingEvents.contains { (event) -> Bool in return eventToAdd.title == event.title && event.startDate == eventToAdd.startDate && event.endDate == eventToAdd.endDate } return exists }