1

I want to write a method, that takes a event object, which has a name and a date parameters. The function requests access / checks access to the event store, creates an EKEvent with the parameters, saves it to the store and then returns the eventidentifier as a String.

So far I have trouble because the eventStore.requestAccess(To:) methods closure escapes, and the string is returned before the EKEvent object actually is created and saved to the store.

My method sits in the code of my EventHelper class, that is the abstraction layer between my EventStore and Apples EKEventStore.

import EventKit

struct Event {
    var name: String
        var date: Date
    var id: String?
}

class EventHelper {

    // MARK: Properties
    var store: EKEventStore!

    // MARK: Methods
    func createCalendarEvent(for event: Event) -> String? {
        // Prepare a place to store the eventIdentifier
        var identifier : String?
    
        // Get access to the eventstore
        store.requestAccess(to: .event) { (granted, error) in
        
            if (granted) && (error == nil) {
           
                    print("Calendar event creation.")
                    print("granted: \(granted)")
                    print("error: \(String(describing: error))")
                
                    // Create a new event kit event
                    let newEvent = EKEvent(eventStore: self.store)
                    newEvent.title = event.name
                    newEvent.startDate = event.date
                
                    // Create a timeinterval for the end date
                    let twoHourTimeInterval = TimeInterval(exactly: 7200)
                    newEvent.endDate = event.date.addingTimeInterval(twoHourTimeInterval!)
                  
                
                    // choose the calendar the event should be assigned to
                    newEvent.calendar = self.store.defaultCalendarForNewEvents
                
                    // try to save the new event in the event store
                    do {
                        try self.store.save(newEvent, span: .thisEvent, commit: true)
                        identifier = newEvent.eventIdentifier
                        print("Saved event with ID: \(String(describing: newEvent.eventIdentifier))")
                     // The event gets created and the ID is printed to the console but at a time when the whole function already has returned (nil)
                    } catch let error as NSError {
                        print("Failed to save event with error: \(error)")
                    }
            }
            else {
                print("Failed to save event with error \(String(describing: error)) or access not granted")
            }
        }
        print("new Event: \(String(describing: identifier))")
        return identifier
    }
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Bernhard
  • 95
  • 6

1 Answers1

1

I found a solution!

Instead of using the .requestAccess(to:completion:) for the event creation. I only use it when I explicitly need to ask for access to the EKEventStore. And to check that I switch on .authorizationStatus(for:)

Here comes the code:

import EventKit

class EventHelper {

    // MARK: Properties
    var store: EKEventStore!


    // MARK: Methods
    /*
     This thing I got from here     https://stackoverflow.com/questions/28379603/how-to-add-an-event-in-the-device-calendar-using-swift more or less
     */
    func createCalendarEvent(for event: Event) -> String? {
        // Act base upon the current authorisation status
        switch EKEventStore.authorizationStatus(for: .event) {
        case EKAuthorizationStatus.notDetermined:
            // Ask for permission
            requestAuthorisationToCalendar()

            // And try again
            return try createCalendarEvent(for: event)

        case EKAuthorizationStatus.denied:
            print("Access to the Event Store was denied.")

        case EKAuthorizationStatus.restricted:
            print("Access to the Event Store was restricted.")

        case EKAuthorizationStatus.authorized:
            // Create a new event
            let newEvent = EKEvent(eventStore: store)
            newEvent.title = event.name
            newEvent.startDate = event.date

            // Create a timeinterval for the end date
            let twoHourTimeInterval = TimeInterval(exactly: 7200)
            newEvent.endDate =     event.date.addingTimeInterval(twoHourTimeInterval!)

            // choose the calender the event should be assinged to
            newEvent.calendar = self.store.defaultCalendarForNewEvents

            // try to save the new event in the event store
            do {
            try self.store.save(newEvent, span: .thisEvent, commit: true)
            print("Saved event with ID: \(String(describing: newEvent.eventIdentifier))")
                return newEvent.eventIdentifier
            } catch let error as NSError {
                print("Failed to save event with error: \(error)")
                return nil
            }
        }
    }

    // MARK: Privat Methods
    private func requestAuthorisationToCalendar() {
        store.requestAccess(to: .event) { (granted, error)  in
            if (granted) && (error == nil) {
                DispatchQueue.main.async {
                    print("User has granted access to calendar")
                }
            } else {
                DispatchQueue.main.async {
                    print("User has denied access to calendar")
                }
            }    
        }
    }
}
Bernhard
  • 95
  • 6