Search code examples
iosekeventekeventstore

EKEvent does not save EKAlarm but no errors on some devices only


I am creating an EKEvent with an EKAlarm as demonstrated in the code below. In most cases, this works perfectly.

However, on a limited number of devices, the alarm does not get set. The event is created in the calendar, but the alarm is missing.

EKEvent* event = [EKEvent eventWithEventStore:eventStore];

event.title = @"Event Title";
event.allDay = YES;
event.notes = @"Event Notes";
event.calendar = calendar ? calendar : eventStore.defaultCalendarForNewEvents;

event.startDate = date;
event.endDate = date;

EKAlarm *alarm = [EKAlarm alarmWithAbsoluteDate:reminderDate];
[event addAlarm:alarm];

NSError* error = nil;

BOOL success = [eventStore saveEvent:event span:EKSpanThisEvent commit:TRUE error:&error];

At the point, success is YES and error is nil. Additionally, the event object has an array of alarms which contains the alarm object. This becomes a problem if I try to remove that alarm and save the event (app crashes because the alarm doesn't actually exist).

I'm not able to determine what is unique about the affected devices. It occurs every time on the following devices:

  • iPhone 6 with iOS 8.1.1
  • iPhone 6 with iOS 8.4
  • iPhone 5 with iOS 8.4

And the following do not have the problem:

  • iPhone 6 with iOS 8.4
  • iPhone 6 with iOS 8.3
  • iPhone 6 with iOS 8.0.2
  • iPhone simulator with iOS 8.1 & iOS 8.4
  • iPhone 5 with iOS 9

All of the above devices are different physical devices. So it doesn't seem to be any particular device model or iOS version.

I have also tried on different calendars, including local calendars and synchronized (e.g. Exchange, Google) calendars. On the affected devices, the issue happens on all calendars.

I have also tried setting / not setting a Time Zone Override, and the Default Alert Times (Settings > Mail, Contacts, Calendars).

Has anyone experienced this issue?


UPDATE:

I have built a test app to isolate the issue from anything else that may be going on inside the original app. It works perfectly on most devices, but the issue still exists on affected devices.

Here is what the EKEvent object looks like immediately after [eventStore saveEvent:event span:EKSpanThisEvent commit:TRUE error:&error]. Note that this call returned YES and error is nil.

EKEvent Object: EKEvent <0x1742e1e00>
{
    EKEvent <0x1742e1e00>
    {    title =        Event Title;
         location =     ;
         calendar =     EKCalendar <0x1740ab4c0> {title = Calendar; type = Exchange; allowsModify = YES; color = #CC73E1;};
         alarms =       (
             "EKAlarm <0x170085190> {triggerDate = 2015-09-02 23:21:53 +0000}"
         );
         URL =          (null);
         lastModified = 2015-08-25 23:21:53 +0000;
         startTimeZone = (null);
         startTimeZone = (null)
     };

    location =          ;
    structuredLocation =     (null);
    startDate =        2015-09-04 14:00:00 +0000;
    endDate =          2015-09-05 13:59:59 +0000;
    allDay =             1;
    floating =           1;
    recurrence =     (null);
    attendees =      (null);
    travelTime =     (null);
    startLocation =  (null);
};

Then I call [eventStore reset] and it looks like this:

EKEvent Object: EKEvent <0x1702e2600>
{
    EKEvent <0x1702e2600>
    {    title =     Event Title;
         location =  ;
         calendar =  EKCalendar <0x1740ad200> {title = Calendar; type = Exchange; allowsModify = YES; color = #CC73E1;};
         alarms =    (null);
         URL =       (null);
         lastModified = 2015-08-25 23:21:53 +0000;
         startTimeZone =  (null);
         startTimeZone =  (null)
    };
    location =          ;
    structuredLocation =     (null);
    startDate =        2015-09-04 14:00:00 +0000;
    endDate =          2015-09-05 13:59:59 +0000;
    allDay =             1;
    floating =           1;
    recurrence =     (null);
    attendees =      (null);
    travelTime =     (null);
    startLocation =  (null);
};

UPDATE #2

I have done some more testing and have been able to reproduce the issue consistently on an Exchange synchronised calendar. I had ruled this out previously as I had asked a client to try selecting a non-Exchange calendar and they reported the issue still occurred.


Solution

  • From what I can tell, this seems to be an iOS bug. I was able to establish that if I add an EKAlarm after saving the EKEvent then save it again, the alarm is successfully added and appears attached to the event in the Calendar app.

    I was therefore able to workaround the issue by resetting the EKEventStore after saving, reloading the EKEvent, and if the EKAlarm is missing, add it and save again.

    if (!error) {
        [eventStore reset];
    
        event = [eventStore eventWithIdentifier:event.eventIdentifier];
    
        if (event.alarms.count < 1) {
            EKAlarm *alarm = [EKAlarm alarmWithAbsoluteDate:reminderDate];
            [event addAlarm:alarm];
    
            [eventStore saveEvent:event span:EKSpanThisEvent commit:TRUE error:&error];
        }
    }