Question

I have a Cordova app with a custom plugin that is creating and updating EKEvents in the user's iCloud calendar.

I am using the following function to find a specific EKEvent based on its URL:

- (EKEvent*) getEventWithURL:(NSString *)pstrURL store:(EKEventStore *)pStore
{


    EKCalendar* calendar = [self getCalendarByName:mstrCalendarName store:pStore createIfDoesNotExist:false];

    NSArray* calendars = [[NSArray alloc] initWithObjects: calendar, nil];

    NSDateFormatter *sDate = [[NSDateFormatter alloc] init];
    [sDate setDateFormat:@"yyyy-MM-dd HH:mm"];
    NSDate *myStartDate = [sDate dateFromString:@"2013-11-01 00:00"];


    NSDateFormatter *eDate = [[NSDateFormatter alloc] init];
    [eDate setDateFormat:@"yyyy-MM-dd HH:mm"];
    NSDate *myEndDate = [eDate dateFromString:@"2014-12-31 23:59"];

    NSPredicate *predicate = [pStore predicateForEventsWithStartDate:myStartDate endDate:myEndDate calendars: calendars];

    // Fetch all events that match the predicate.
    NSArray *events = [pStore eventsMatchingPredicate:predicate];

    EKEvent *foundEvent = nil;
    EKEvent *event;

    for (id oEvent in events)
    {
        event = (EKEvent *)oEvent;

        if ([event.URL isEqual:[NSURL URLWithString:pstrURL]])
        {
            foundEvent = event;
            break;
        }
    }

    return foundEvent;
}

It is then modified (start and end dates are changed) and saved in another method with the following code:

EKEvent *myEvent = nil;

BOOL saved = false;


EKCalendar* calendar = nil;

if(pstrCalendarTitle == nil)
{
    calendar = pStore.defaultCalendarForNewEvents;
}
else
{
    calendar = [self getCalendarByName: pstrCalendarTitle store: pStore createIfDoesNotExist:true];
}


// find event if it exists
myEvent = [self getEventWithURL:[NSString stringWithFormat: @"custom://%@", pstrTSDID ] store:pStore];


// if an event wasn't found, create a new one
if (myEvent == nil)
{
    myEvent = [EKEvent eventWithEventStore: pStore];
}

// set all the fields to new values
myEvent.title = pstrTitle;
myEvent.location = pstrLocation;
myEvent.notes = pstrMessage;
myEvent.startDate = pdtStartDate;
myEvent.endDate = pdtEndDate;
myEvent.calendar = calendar;
myEvent.URL = [NSURL URLWithString:[NSString stringWithFormat: @"custom://%@", pstrTSDID ]];

// only add an alarm if one hasn't been created already
if ([[myEvent alarms] count] == 0)
{
    EKAlarm *reminder = [EKAlarm alarmWithRelativeOffset:-2*60*60];
    [myEvent addAlarm:reminder];
}

When creating a whole bunch of EKEvents (about 30 in a row) I don't get the EXC_BAD_ACCESS error, however when updating events I get the EXC_BAD_ACCESS error intermittently. Sometimes it is on the first update, and sometimes I am able to update 10 before seeing the error, which then crashes my app.

I suspect it may have something to do with the foundEvent variable not being retained, however my project is using ARC so it is my understanding that I don't need to do any memory management tasks. Unless ARC is getting confused with the way the event variable is being cast and then passed around in the loop in getEventWithURL?

For full disclosure, I do have Enable Zombie Objects enabled and the stack trace that I see doesn't reference any of my methods specifically, it starts at start_wqthread and then references some EKEventStore _databasechangedexternally internal methods.

Was it helpful?

Solution

For what it's worth I wasn't able to figure out what the issue was with modifying the events so I am instead deleting the event (if it exists) and creating a new one. My getEventWithURL method is now called deleteEventWithURL which does the removal of the event from the store. The app is no longer crashing after making this change.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top