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
}