I am trying to request access to calendars in a SwiftUI MacOS app but it immediately denies it.
Below is some testable code highlighting what I want to achieve. Many thanks.
In my previous experience with requesting private information on MacOS a notification should appear instead of the popUp on iOS.
I'm still trying to figure out EventKit for SwiftUI so please excuse any mistakes.
struct ContentView: View {
let eventStore = EKEventStore()
var body: some View {
Text("Test")
.onAppear{
checkCalendarAuthorizationStatus()
}
}
func checkCalendarAuthorizationStatus() {
switch EKEventStore.authorizationStatus(for: .event) {
case .authorized:
insertEvent(store: eventStore)
case .denied:
print("Access denied")
case .notDetermined:
// 3
eventStore.requestAccess(to: .event, completion:
{(granted: Bool, error: Error?) -> Void in
if granted {
self.insertEvent(store: eventStore)
} else {
print("Access denied")
}
})
default:
print("Case default")
}
}
func insertEvent(store: EKEventStore) {
// 1
let calendars = store.calendars(for: .event)
for calendar in calendars {
// 2
if calendar.title == "Calendar" {
// 3
let startDate = Date()
// 2 hours
let endDate = startDate.addingTimeInterval(2 * 60 * 60)
// 4
let event = EKEvent(eventStore: store)
event.calendar = calendar
event.title = "New Meeting"
event.startDate = startDate
event.endDate = endDate
// 5
do {
try store.save(event, span: .thisEvent)
}
catch {
print("Error saving event in calendar") }
}
}
}
}
You should not check status, but request access with EKEventStore().requestAccess(... directly, as documented
/**
@method requestAccessToEntityType:completion:
@discussion Users are able to grant or deny access to event and reminder data on a per-app basis. To request access to
event and/or reminder data, call -requestAccessToEntityType:completion:. This will not block the app while
the user is being asked to grant or deny access.
Until access has been granted for an entity type, the event store will not contain any calendars for that
entity type, and any attempt to save will fail. The user will only be prompted the first time access is
requested; any subsequent instantiations of EKEventStore will use the existing permissions. When the user
taps to grant or deny access, the completion handler will be called on an arbitrary queue.
*/
@available(macOS 10.9, *)
open func requestAccess(to entityType: EKEntityType, completion: @escaping EKEventStoreRequestAccessCompletionHandler)
so use the following
func checkCalendarAuthorizationStatus() {
eventStore.requestAccess(to: .event, completion:
{(granted: Bool, error: Error?) -> Void in
if granted {
self.insertEvent(store: eventStore)
} else {
print("Access denied")
}
})
}
and make sure NSCalendarsUsageDescription
description is added in Info.plist
.