11

I'm writing an iPhone app that will use the EventKit framework to create new events in the user's Calendar. That part works pretty well (except for the wonky way it handles the timezone -- but that's another issue). What I can't figure out is how to get a list of the user's calendars so that they can choose which calendar to add the event to. I know that its an EKCalendar object but the docs don't show any way to get the whole collection.

Thanks in advance,

Mark

mpemburn
  • 2,776
  • 1
  • 35
  • 41

3 Answers3

21

Searching through the documentation reveals an EKEventStore class that has a calendars property.

My guess is that you'd do something like:

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

EDIT: As of iOS 6, you need to specify whether you want to retrieve calendars of reminders or calendars of events:

EKEventStore * eventStore = [[EKEventStore alloc] init];
EKEntityType type = // EKEntityTypeReminder or EKEntityTypeEvent
NSArray * calendars = [eventStore calendarsForEntityType:type];    
fabian789
  • 8,348
  • 4
  • 45
  • 91
Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • Excellent! Thanks! Initial experiments confirm that it's returning an array of calendars. – mpemburn Jan 08 '11 at 21:15
  • 2
    as the property 'calendars' is deprecated in iOS 6.0, you should change to NSArray *calendars = [eventStore calendarsForEntityType:EKEntityTypeEvent]; – Riad Krim Sep 06 '13 at 09:55
7

The code I used to get a useable NSDictionary of calendar names and types is like this:

//*** Returns a dictionary containing device's calendars by type (only writable calendars)
- (NSDictionary *)listCalendars {

    EKEventStore *eventDB = [[EKEventStore alloc] init];
    NSArray * calendars = [eventDB calendars];
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    NSString * typeString = @"";

    for (EKCalendar *thisCalendar in calendars) {
        EKCalendarType type = thisCalendar.type;
        if (type == EKCalendarTypeLocal) {
            typeString = @"local";
        }
        if (type == EKCalendarTypeCalDAV) {
            typeString = @"calDAV";
        }
        if (type == EKCalendarTypeExchange) {
            typeString = @"exchange";
        }
        if (type == EKCalendarTypeSubscription) {
            typeString = @"subscription";
        }
        if (type == EKCalendarTypeBirthday) {
            typeString = @"birthday";
        }
        if (thisCalendar.allowsContentModifications) {
            NSLog(@"The title is:%@", thisCalendar.title);
            [dict setObject: typeString forKey: thisCalendar.title]; 
        }
    }   
    return dict;
}
mpemburn
  • 2,776
  • 1
  • 35
  • 41
  • ^ You never release the event store or the dict, so those are memory leaks. Calendars can probably have the same title using that as a key into the dict may not work. – n13 Aug 17 '11 at 07:19
  • 1
    calendars property has been deprecated in iOS 6. – Markus Rautopuro Nov 26 '13 at 18:36
  • the NSArray *calendars line only works for iOS 6 and below, for the 6> you need to use this: NSArray * calendars = [eventStore calendarsForEntityType: EKEntityTypeEvent]; – cesarferreira Sep 19 '14 at 10:57
2

I get the list of calendars OK - the problem is I don't get a user-displayable list. The calendar.title property is null for all of them; I don't see any kind of id property either.

-> Update: It works now for me. The mistake I had made was to put the eventStore object in a temporary variable, then get the list of calendars, then release the eventStore. Well if you do that all your calendars go away too. Containment is not strictly object oriented in some of the iOS frameworks, and this is an example of that. That is, the calendar object is dependent on the event store, it's not its own, separate entity.

Anyway -the solution above is fine!

n13
  • 6,843
  • 53
  • 40