I would be interested in knowing how to add a calendar event in the device, but using swift. I know there are some examples made in Objective-C, but at the moment nothing in swift. Many thanks.
-
Swift 2.0 Implementation added : [HERE ON LINK](http://stackoverflow.com/questions/246249/programmatically-add-custom-event-in-the-iphone-calendar/34790334#34790334) – Dashrath Jan 14 '16 at 13:04
7 Answers
Note: If your app is crashing with This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCalendarsUsageDescription key with a string value explaining to the user how the app uses this data.
, you'll need to add NSCalendarsUsageDescription
to your info.plist. Can follow the example here.
Swift 5.0 Version
import Foundation
import EventKit
let eventStore : EKEventStore = EKEventStore()
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccess(to: .event) { (granted, error) in
if (granted) && (error == nil) {
print("granted \(granted)")
print("error \(error)")
let event:EKEvent = EKEvent(eventStore: eventStore)
event.title = "Test Title"
event.startDate = Date()
event.endDate = Date()
event.notes = "This is a note"
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let error as NSError {
print("failed to save event with error : \(error)")
}
print("Saved Event")
}
else{
print("failed to save event with error : \(error) or access not granted")
}
}
Reference : https://gist.github.com/mchirico/d072c4e38bda61040f91
-
21for who doesn't know you must import : import EventKit to make it work – Mostafa Sultan Sep 22 '15 at 15:08
-
1it gives error "use of unresolved identifier EKEntityTypeEvent". am I missing something ? – Dashrath Jan 14 '16 at 12:26
-
2@Dashrath Use `EKEntityType.Event` (few changes in Swift 2.0) instead – Fares K. A. Feb 12 '16 at 20:49
-
This is not working in iOS 9 devices. Any idea why? I tried the same code, but in ios9 devices, permission is not asking. – Sneha Mar 15 '17 at 04:31
-
1
-
3You need to add "Privacy - Calendars Usage Description" in info.plist – ThetNaing Mizo Aug 04 '17 at 03:35
Swift 3.0 compatible:
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
}
})
}
And also import EventKit
So you can easily call this method from everywhere:
addEventToCalendar(title: "Girlfriend birthday", description: "Remember or die!", startDate: NSDate(), endDate: NSDate())
If you prefer, you can put this method inside an utiliy class and define it as 'static'.

- 167
- 3
- 9

- 21,000
- 15
- 120
- 146
-
5You need to add "Privacy - Calendars Usage Description" in info.plist. – ThetNaing Mizo Aug 04 '17 at 03:34
-
2thanks for @ThetNaingMizo for the info.plist info. I will take it a little further and will add the complete entry on the info.plist Key : Privacy - Calendars Usage Description Value : $(PRODUCT_NAME) calendar events – Jiraheta Apr 18 '18 at 16:22
You need to add "Privacy - Calendars Usage Description" to info.plist. Following code works with latest version of xcode and swift 3.
import EventKit
class EventHelper
{
let appleEventStore = EKEventStore()
var calendars: [EKCalendar]?
func generateEvent() {
let status = EKEventStore.authorizationStatus(for: EKEntityType.event)
switch (status)
{
case EKAuthorizationStatus.notDetermined:
// This happens on first-run
requestAccessToCalendar()
case EKAuthorizationStatus.authorized:
// User has access
print("User has access to calendar")
self.addAppleEvents()
case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
// We need to help them give us permission
noPermission()
}
}
func noPermission()
{
print("User has to change settings...goto settings to view access")
}
func requestAccessToCalendar() {
appleEventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
DispatchQueue.main.async {
print("User has access to calendar")
self.addAppleEvents()
}
} else {
DispatchQueue.main.async{
self.noPermission()
}
}
})
}
func addAppleEvents()
{
let event:EKEvent = EKEvent(eventStore: appleEventStore)
event.title = "Test Event"
event.startDate = NSDate() as Date
event.endDate = NSDate() as Date
event.notes = "This is a note"
event.calendar = appleEventStore.defaultCalendarForNewEvents
do {
try appleEventStore.save(event, span: .thisEvent)
print("events added with dates:")
} catch let e as NSError {
print(e.description)
return
}
print("Saved Event")
}
}

- 1,251
- 16
- 18
I was able to adjust this and eliminate the compiler error mentioned in the comments to the answers above (and a few others), as follows:
var eventStore : EKEventStore = EKEventStore()
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: {
(granted, error) in
if (granted) && (error == nil) {
print("granted \(granted)")
print("error \(error)")
var event:EKEvent = EKEvent(eventStore: eventStore)
event.title = "Test Title"
event.startDate = NSDate()
event.endDate = NSDate()
event.notes = "This is a note"
event.calendar = eventStore.defaultCalendarForNewEvents
eventStore.saveEvent(event, span: EKSpan.ThisEvent, error: nil)
print("Saved Event")
}
})
However, I still get the following error at the bottom regarding "EKSpan.ThisEvent" : Incorrect argument label in call (have ':span:error:', expected ':span:commit:').
I tried changing "error" to "commit," but it gave me a compiler error saying it expected a Bool instead of nil. It seems like a problem having to do with updates in swift syntax.
Edit: I ended up following this tutorial and was able to get it to work.
First, ask permission to access the calendar and (if that permission is granted) call a function to add the event.
var savedEventId : String = "" func requestAccessPermission() { let eventStore = EKEventStore() let startDate = NSDate() let endDate = startDate.dateByAddingTimeInterval(60 * 60) // Ends one hour later if (EKEventStore.authorizationStatusForEntityType(.Event) != EKAuthorizationStatus.Authorized) { eventStore.requestAccessToEntityType(.Event, completion: { granted, error in self.createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate) }) } else { createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate) } }
The function that is called in the above code snippet to add the event:
func createEvent(eventStore: EKEventStore, title: String, startDate: NSDate, endDate: NSDate) { let event = EKEvent(eventStore: eventStore) event.title = title event.startDate = startDate event.endDate = endDate event.calendar = eventStore.defaultCalendarForNewEvents do { try eventStore.saveEvent(event, span: .ThisEvent) savedEventId = event.eventIdentifier } catch { print("Error Saving") } }

- 1,348
- 2
- 17
- 42

- 595
- 4
- 18
This was really slow on iOS 11.2 Xcode 9.2, so I modified Luca Davanzo's answer to use queues (works a lot faster):
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
DispatchQueue.global(qos: .background).async { () -> Void in
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
}
})
}
}

- 1,181
- 8
- 5
Async/await without completion handlers:
func addCalendarEvent(eventTitle: String, startDate: Date, endDate: Date) {
Task {
do {
let eventStore = EKEventStore()
let requestResult: Bool = try await eventStore.requestAccess(to: .event)
guard requestResult else {
debugPrint("Couldn't not create a calendar event. Calendar access denied.")
return
}
let event = EKEvent(eventStore: eventStore)
event.title = eventTitle
event.startDate = startDate
event.endDate = endDate
event.calendar = eventStore.defaultCalendarForNewEvents
try eventStore.save(event, span: .thisEvent)
} catch {
debugPrint("Couldn't not create a calendar event. Error: \(error.localizedDescription)")
return
}
}
}

- 21
- 2
same with location and alert
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, location: String?, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
DispatchQueue.global(qos: .background).async { () -> Void in
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let alarm = EKAlarm(relativeOffset: -3600.0)
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.alarms = [alarm]
event.location = location
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
print ("\(#file) - \(#function) error: \(e.localizedDescription)")
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
print ("\(#file) - \(#function) error: \(error)")
}
})
}
}

- 530
- 6
- 9