Question

I have recently released an app and instantly found an annoying bug. There is a button to add events to iCal. When pressed the user is asked to allow the app access to the calendar. If the user clicks ok then an error message is displayed (the if(!saved) in the code). However, if the user then restarts the app then everything works perfectly (i.e. item is added to iCal without needing to ask permission).

What is particularly annoying about the bug is it doesn't show up in the simulator, or in any device where the app was previously installed (including after deleting the app and reseting privacy settings). This makes it difficult to replicate.

- (IBAction)addToCal:(id)sender{

EKEventStore *eventStore = self.filmController.eventStore;
/* I have moved this code to a new method, called after access is requested. See the edit...    
EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
event.title     = self.film.title;
event.startDate = self.show.date;
event.endDate   = [[NSDate alloc] initWithTimeInterval:(60*[self.film.length integerValue]) sinceDate:event.startDate];
event.location = @"Cinema";
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
*/
if([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)]){
    [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        if(granted) {
            BOOL saved = [self saveEventToEventStore:eventStore];

            NSString *msg;
            NSString *title;

            if(!saved) {
                title = @"Sorry: We can't access your calendar";
                msg = @"Please check your access settings for the app in Settings>>Privacy>>Calendars (and try turning permissions 'Off' then 'On'). If you still can't save events then please let us know.";
            }
            else {
                title = @"Added";
                msg = @"Item added to calendar";
            }
            UIAlertView *eventAlert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
            [eventAlert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

        }
        else {
            UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Sorry: We can't access your calendar" message:@"You must change the setting for the app in Settings>>Privacy>>Calendars." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
            [errorAlert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];
        }
    }];
}
else {
    [self saveEventToEventStore:eventStore];
}
}

-(BOOL) saveEventToEventStore:(EKEventStore *)eventStore {

//Set event details
EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
event.title     = self.film.title;
event.startDate = self.show.date;
event.endDate   = [[NSDate alloc] initWithTimeInterval:(60*[self.film.length integerValue]) sinceDate:event.startDate];
event.location = @"Cinema";
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
//event details end

NSError *err;
return [eventStore saveEvent:event span:EKSpanThisEvent error:&err];
}

any help would be greatly appreciated....

Nick

EDIT: I've been thinking a lot about this, but it's still not obvious what is wrong. My only guess is that I am setting my event details before I requestAccess. This could then be raising some error (probably when setting the calendar), which causes the save to fail. Restarting the app starts it from a state where access is already granted, therefore avoiding the error. I'm still not entirely happy with this guess as I would assume that it'd only cause an issue the first time the 'add to iCal' button is pressed, whereas my issue happens for subsequent presses.

I've added the new (more complete) code above, which puts the event creation after the requestAccess. Sadly I've ran out of devices to test it on, but if I find one I will update if this worked.

Was it helpful?

Solution

So finally managed to test my edit above and it works. So I think the problem is calling

[event setCalendar:[eventStore defaultCalendarForNewEvents]];

before

[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top