0

I have two (2) calendars (iCal) on my iPad (one personal, one for the app). They are sync'd to my iMac for testing only. (Saves me time making entries to the specific app calendar).

I am currently writing an app that needs to access the app's calendar. It is the primary calendar on the iPad. I am trying to get Apple's SimpleEKDemo (unmodified) to work with the app's calendar, but so far I can't even get it not crash, much less to return anything. I have been looking at Google and SO questions for hours now, and decided it's time to call in the big guns.

This is the code where it's crashing:

- (void)viewDidLoad
{
    self.title = @"Events List";

    // Initialize an event store object with the init method. Initilize the array for events.
    self.eventStore = [[EKEventStore alloc] init];

    self.eventsList = [[NSMutableArray alloc] initWithArray:0];

    // Get the default calendar from store.
    self.defaultCalendar = [self.eventStore defaultCalendarForNewEvents];  //  <---- crashes here    --------

    //  Create an Add button
    UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:
                                      UIBarButtonSystemItemAdd target:self action:@selector(addEvent:)];
    self.navigationItem.rightBarButtonItem = addButtonItem;
    [addButtonItem release];

    self.navigationController.delegate = self;

    // Fetch today's event on selected calendar and put them into the eventsList array
    [self.eventsList addObjectsFromArray:[self fetchEventsForToday]];

    [self.tableView reloadData];
}

This is the output from the "crash":

2012-10-05 14:33:12.555 SimpleEKDemo[874:907] defaultCalendarForNewEvents failed: Error Domain=EKCADErrorDomain Code=1013 "The operation couldn’t be completed. (EKCADErrorDomain error 1013.)"

I need to make sure I'm on the correct calendar... how do I do that?

SpokaneDude
  • 4,856
  • 13
  • 64
  • 120
  • What is the output of the crash? – WrightsCS Oct 05 '12 at 21:28
  • Oops... I edited the question to add it... sorry... – SpokaneDude Oct 05 '12 at 21:33
  • OK... I changed the code to this: // Get the default calendar from store. self.defaultCalendar = [self.eventStore calendarWithIdentifier:@"Prager Software"]; but it doesn't appear it's working because it's crashing on the "Fetch today' event" due to nothing is there. How do I verify the name of the calendar? – SpokaneDude Oct 05 '12 at 21:44

2 Answers2

12

You need to ensure you ask permission before trying to access the Event Store. Note that you need to only call this once. If the user denies access, they need to go to iOS Settings (see comment in code) to enable permissions for your app.

/* iOS 6 requires the user grant your application access to the Event Stores */
if ([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)])
{
    /* iOS Settings > Privacy > Calendars > MY APP > ENABLE | DISABLE */
    [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
     {
         if ( granted )
         {
             NSLog(@"User has granted permission!");
         }
         else
         {
             NSLog(@"User has not granted permission!");
         }
     }];
}

In iOS 5, you are only allowed to access Events (EKEntityTypeEvent) in the Event Store, unlike in iOS 6, where you can access Reminders (EKEntityTypeReminder). But you need the above code to at least get granted 1 time.

I should also mention that you need to be granted permission BEFORE you access the EventStore, in your case: [self.eventStore defaultCalendarForNewEvents];.

Also, defaultCalendarForNewEvents would be the correct way to access the users Default Calendar. If you wish to access a calendar with another name, then you need to iterate through the calendars and choose the appropriate one based on the results returned.

WrightsCS
  • 50,551
  • 22
  • 134
  • 186
  • I think we're on the right track here (the question for permission is asked, but it doesn't wait for the answer)... when you say "iterate through the calendars", what method am I supposed to be using that will give me the list of calendars? In iOS 6, "calendars" is deprecated, and I don't see anything that will give me the same info. – SpokaneDude Oct 05 '12 at 21:48
  • See **`EKCalendar`** `title` for the name of the calendars. You should know how to iterate through the calendars with a for loop. – WrightsCS Oct 05 '12 at 22:04
  • I thought it was more complicated than a -for loop... thank you so much for your help... I really appreciate it... – SpokaneDude Oct 05 '12 at 22:12
  • 1
    In iOS 6 use **[self.eventStore calendarsForEntityType:EKEntityTypeEvent];** to get the list of calendars. – jd291 Oct 18 '12 at 09:23
  • Don't worry about your app being TERMINATED by iOS when the user changes the privacy settings while your app is running. This is known/expected behavior, and not a bug: http://stackoverflow.com/questions/12652502/app-killed-by-sigkill-when-changing-privacy-settings – Gorm May 18 '13 at 16:18
3

//Check if iOS6 or later is installed on user's device *********

if([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {

    //Request the access to the Calendar
    [eventStore requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted,NSError* error){

        //Access not granted-------------
        if(!granted){
            NSString *message = @"Hey! I Can't access your Calendar... check your privacy settings to let me in!";
            UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Warning"
                                                               message:message
                                                              delegate:self
                                                     cancelButtonTitle:@"Ok"
                                                     otherButtonTitles:nil,nil];
            //Show an alert message!
            //UIKit needs every change to be done in the main queue
            dispatch_async(dispatch_get_main_queue(), ^{[alertView show];});

            //Access granted------------------
        }
        else
        {
            self.defaultCalendar=[self.eventStore defaultCalendarForNewEvents];

        }
    }];
}

//Device prior to iOS 6.0  *********************************************
else{
    self.defaultCalendar=[self.eventStore defaultCalendarForNewEvents];
    }
prohuutuan
  • 230
  • 2
  • 7