Search code examples
iosswifteventkitekevent

EKEventEditViewController is presented with a disabled Add button


The problem

I'm presenting a EKEventEditViewController view with some predefined information. If the user doesn't want to change this information, he should be able to tap Add to add the event to the calendar.

The problem is, the Add button is disabled by default. It is only enabled if the user changes something (like the event name or the Calendar, for example).

Snippet of code

class EventManager {

    private var eventEditViewController: EKEventEditViewController?
    private let eventStore = EKEventStore()

    func addToCalendar(_ eventData: EventData) {
        let event = createEvent(eventData)
        presentEvent(event)
    }

    private func createEvent(_ eventData: EventData) -> EKEvent {
        let event = EKEvent(eventStore: eventStore)
        event.title = "My event"
        event.startDate = Date()
        event.endDate = Date()
        event.isAllDay = true
        event.calendar = eventStore.defaultCalendarForNewEvents
        event.availability = .free
        event.addAlarm(EKAlarm.init(absoluteDate: event.startDate))
        event.url = URL(string: "http://myurl.com/")
        return event
    }

    private func presentEvent(_ event: EKEvent) {
        DispatchQueue.main.async {
            self.eventEditViewController = EKEventEditViewController()
            self.eventEditViewController!.eventStore = self.eventStore
            self.eventEditViewController!.event = event
            self.eventEditViewController!.editViewDelegate = self

            self.viewController?.present(self.eventEditViewController!, animated: true)
        }
    }

}

extension EventManager: EKEventEditViewDelegate {

    func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
        eventEditViewController?.dismiss(animated: true, completion: {
            self.delegate.finish(result: CalendarResult.fromAction(action))
        })
    }

}

EKEventEditViewController

Here's how the EKEventEditViewController is presented:

how the <code>EKEventEditViewController</code> is presented

One more thing

Another thing I've noticed is that when I remove the start and end date from my EKEvent object, the Add button is enabled by default.

How can I configure my EKEvent object, in a way that it has a custom start and end date, and at the same time enable the Add button of EKEventEditViewController by default?


Solution

  • This was fixed on iOS 13.3 beta

    On iOS 12.2.x: Apparently the EKEventEditViewController is treating your event as an already existing event and not as a new event. Thus disabling the Add button since no changes where made (Apple bug).

    A small way to prove it is to try to edit the title by removing a character, this will enable the add because now it changed from the original. If you put back the same character you just removed it will disable the Add button again.

    A workaround we found was to subclass the EKEventEditViewController like this:

    final class FixedEventEditViewController: EKEventEditViewController {
        /// Set this variable instead of the `event` property to avoid a crash on iOS 12+ when a fixed timezone is set
        var deferredEvent: EKEvent?
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    
            if let deferredEvent = self.deferredEvent {
                // Trick iOS into thinking that the event changed so it enables the Add button on iOS 13.2.x -> Fixed starting iOS 13.3
                let titleDeferred = deferredEvent.title
                deferredEvent.title = nil
                // Set the event to the new deferred event that contains no title
                self.event = deferredEvent
                // Set the original title. This will let iOS think the event changed and enable the Add button
                self.event?.title = titleDeferred
            }
        }
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            // This is to hide the keyboard
            self.view.endEditing(true)
        }
    }