Search code examples
iosobjective-cekeventekeventstoreekeventkit

Loading bulk event in ios calendar get error


I am trying to do a massive load of events on a calendar either local or in gmail (the calendar chooses the user as I describe in the following answer) using .

Adding an event with the functions I've put below works fine for me, but when I have to do a massive load of eg 527 events (since I'm trying to add a student's school calendar) it does not work correctly.

When doing the bulk load I inserted well about 100 events or so and then it starts to crash and crash the app.

The errors that it gives me are the following:

2016-11-17 17:23:35.966 [230:11481] Calendar was not set: 1 Error Domain=EKErrorDomain Code=1 "No calendar selected." UserInfo={NSLocalizedDescription=No calendar selected.}

2016-11-17 17:23:49.545 [230:12644] Connectioninterrupted!

2016-11-17 17:23:49.568[230:12587] Error getting changed object IDs since timestamp 501092601.149441 from daemon: Error Domain=NSMachErrorDomain Code=4097 "unknown error code"

My question is this: Is there any error in my massive loading approach or in the functions I have done? or else Is there any other better way to do a massive load of events?

Function that inserts the list of events:

- (int) addCalendarEvents: (EKCalendar *) cal {

    int num = 0;

    for (int i=0; i < [calendario.eventos count]; i++) {

        NSDictionary * nextDict = [calendario.eventos objectAtIndex:i];
        Evento_DTO * evento_dto = [[Evento_DTO alloc] initWithEventos:nextDict];

        BOOL res = [self addEventCalendar: evento_dto calendar: cal];

        if(res){
            num++;
        }
    }

    return num;
}

And the function that adds the event to the calendar is as follows:

-(BOOL)addEventCalendar: (Evento_DTO *) evento calendar: (EKCalendar *) cal{

    __block BOOL res = NO;

    if (!SYSTEM_VERSION_LESS_THAN(@"6.0")) {
        // iOS 6 and later

        EKEventStore *eventStore = [[EKEventStore alloc] init];

        //We get the dates of the event
        Fecha_DTO *fechaStart = [[Fecha_DTO alloc] initWithFecha:(NSDictionary *)evento.dtStart];
        Fecha_DTO *fechaEnd = [[Fecha_DTO alloc] initWithFecha:(NSDictionary *)evento.dtEnd];

        // Format the dates to type NSDate
        // Start Date
        NSDateFormatter* df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"yyyyMMdd'T'HHmmss"];

        if (fechaStart.tzid == nil) {
            [df setTimeZone: [NSTimeZone systemTimeZone]];
        }else{
            [df setTimeZone:[NSTimeZone timeZoneWithName:fechaStart.tzid]];
        }
        NSDate* parsedDateS = [df dateFromString: fechaStart.fecha];

        // End Date
        NSDateFormatter* df2 = [[NSDateFormatter alloc] init];
        [df2 setDateFormat:@"yyyyMMdd'T'HHmmss"];

        if (fechaEnd.tzid == nil) {
            [df2 setTimeZone: [NSTimeZone systemTimeZone]];
        }else{
            [df2 setTimeZone:[NSTimeZone timeZoneWithName:fechaEnd.tzid]];
        }
        NSDate* parsedDateE = [df2 dateFromString: fechaEnd.fecha];

        //rRules
        NSString *rfc2445String = evento.rRule; // Usando la libreria EKRecurrenceRule+RRULE.m
        EKRecurrenceRule *recurrenceRule;
        if (![rfc2445String isEqualToString:@""]) {
            recurrenceRule = [[EKRecurrenceRule alloc] initWithString:rfc2445String andTimezone:fechaStart.tzid];
           // NSLog(@"RRule: %@", recurrenceRule);
        }

        if(parsedDateS!=nil){

            [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {

                if (granted) {
                    EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
                    event.title     = evento.summary;
                    event.notes     = evento.description;
                    event.startDate = parsedDateS;
                    event.endDate  = parsedDateE;
                    event.location = evento.location;

                    if (![rfc2445String isEqualToString:@""]) 
                     event.recurrenceRules = [NSArray arrayWithObject:recurrenceRule];


                    event.calendar = [eventStore calendarWithIdentifier: cal.calendarIdentifier];

                    //[event setCalendar:[eventStore defaultCalendarForNewEvents]];
                    NSError *err = nil;

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

                    if(!success){
                        if (err) {
                            NSLog(@"Calendar was not set: %li %@", (long)err.code, err.description);
                        }
                    }else{

                        //NSLog(@"Added Event");
                        res = YES;
                    }

                } else {
                    // code here for when the user does NOT allow your app to access the calendar
                    alerta = [[UIAlertView alloc]initWithTitle:AMLocalizedString(@"Error", @"")
                                                       message:AMLocalizedString(@"errorPermisosCal", @"")
                                                      delegate:self
                                             cancelButtonTitle:@"OK"
                                             otherButtonTitles:nil, nil];
                    [alerta show];
                }
            }];
        }else{
            NSLog(@"The start date is null");
        }

        df = nil;
        df2 = nil;
    }else{

        alerta = [[UIAlertView alloc]initWithTitle:AMLocalizedString(@"Error", @"")
                                           message:AMLocalizedString(@"VersionEvento", @"")
                                          delegate:self
                                 cancelButtonTitle:@"OK"
                                 otherButtonTitles:nil, nil];
        [alerta show];
    }
    return res;
}

Solution

  • Finally I have been able to perform the massive bulk of events without failures, I have modified the methods being as follows:

    - (void) addCalendarEvents: (EKCalendar *) cal store: (EKEventStore *) eventStore {
    
        if (!SYSTEM_VERSION_LESS_THAN(@"6.0")) {
            // iOS 6 and later
    
            [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
    
                if (granted) {
                    //se añade cada uno de los eventos
                    for (int i=0; i < [calendario.eventos count]; i++) {
                        @autoreleasepool {
                            NSDictionary * nextDict = [calendario.eventos objectAtIndex:i];
                            Evento_DTO * evento_dto = [[Evento_DTO alloc] initWithEventos:nextDict];
    
                            [self addEventCalendar: evento_dto calendar: cal.calendarIdentifier store: eventStore];
                        }
                    }
                } else {
                    // code here for when the user does NOT allow your app to access the calendar
                    alerta = [[UIAlertView alloc]initWithTitle:AMLocalizedString(@"Error", @"")
                                                       message:AMLocalizedString(@"errorPermisosCal", @"")
                                                      delegate:self
                                             cancelButtonTitle:@"OK"
                                             otherButtonTitles:nil, nil];
                    [alerta show];
                }
            }];
        }else{
    
            alerta = [[UIAlertView alloc]initWithTitle:AMLocalizedString(@"Error", @"")
                                               message:AMLocalizedString(@"Event version", @"")
                                              delegate:self
                                     cancelButtonTitle:@"OK"
                                     otherButtonTitles:nil, nil];
            [alerta show];
        }
    }
    

    And the function that adds the event to the calendar is as follows:

    -(void)addEventCalendar: (Evento_DTO *) evento calendar: (NSString *) cal store: (EKEventStore *) eventStore{
    
        //Obtenemos las fechas del evento
        Fecha_DTO *fechaStart = [[Fecha_DTO alloc] initWithFecha:(NSDictionary *)evento.dtStart];
        Fecha_DTO *fechaEnd = [[Fecha_DTO alloc] initWithFecha:(NSDictionary *)evento.dtEnd];
    
         // Format the dates to type NSDate
        // Start Date
        NSDateFormatter* df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"yyyyMMdd'T'HHmmss"];
    
        if (fechaStart.tzid == nil) {
            [df setTimeZone: [NSTimeZone systemTimeZone]];
        }else{
            [df setTimeZone:[NSTimeZone timeZoneWithName:fechaStart.tzid]];
        }
        NSDate* parsedDateS = [df dateFromString: fechaStart.fecha];
    
        // End Date
        NSDateFormatter* df2 = [[NSDateFormatter alloc] init];
        [df2 setDateFormat:@"yyyyMMdd'T'HHmmss"];
    
        if (fechaEnd.tzid == nil) {
            [df2 setTimeZone: [NSTimeZone systemTimeZone]];
        }else{
            [df2 setTimeZone:[NSTimeZone timeZoneWithName:fechaEnd.tzid]];
        }
        NSDate* parsedDateE = [df2 dateFromString: fechaEnd.fecha];
    
        //rRules
        NSString *rfc2445String = evento.rRule; 
        EKRecurrenceRule *recurrenceRule;
    
        if (![rfc2445String isEqualToString:@""]) {
            recurrenceRule = [[EKRecurrenceRule alloc] initWithString:rfc2445String andTimezone:fechaStart.tzid];
            //NSLog(@"RRule: %@", recurrenceRule);
        }
    
        if(parsedDateS!=nil){
    
            EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
            event.title     = evento.summary;
            event.notes     = evento.description;
            event.location = evento.location;
            event.startDate = parsedDateS;
            event.endDate  = parsedDateE;
    
            if (![rfc2445String isEqualToString:@""]) 
                event.recurrenceRules = [NSArray arrayWithObject:recurrenceRule];
    
            event.calendar = [eventStore calendarWithIdentifier: cal];
    
            NSError *err = nil;
    
            BOOL success = [eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
    
            if(!success){
                if (err) {
                    NSLog(@"Calendar was not set: %li %@", (long)err.code, err.description);
                }
            }else{
    
                NSLog(@"Added Event");
            }
        }else{
            NSLog(@"The start date is null");
        }
    
        df = nil;
        df2 = nil;
    }
    

    I hope it helps somebody.