Handling Access to Calendars in iOS 6

I had to laugh at my last post. I went on hiatus in August 2010 and now I’m back, in 2012. I’ve been busy working on Skedi Family Calendar, which aggregates calendar data from different vendors such as Google Calendar, Microsoft Exchange, etc.

Anyway, the latest release of iOS (6.0) isolates a user’s calendars and blocks access by default. This presented a problem for us at Rodax Software because we also support earlier versions of iOS (i.e., 4 and 5) and we wanted to avoid using conditional compilation.

In iOS 6, access to the calendars is controlled through the EKEventStore class. In the past, we’d call a alloc/init and that was it.  This is unchanged; however, now we need to request permission and if granted, we can access the users calendars and events. Note: This request can only be performed once, which I’ll cover later.

 _store = [[EKEventStore alloc] init];

So, if we need to support earlier versions of iOS, how can we avoid using ugly preprocessor macros? Simple, use the power of Objective-C’s dynamic typing. In iOS 6, the method to request access in EKEventStore is requestAccessToEntityType. Hence, we need to determine if it’s available.

if([_store respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {
	//invoke requestAccessToEntityType...
}

If the statement is true, request access:

[_store requestAccessToEntityType:EKEntityTypeEvent
                       completion:^(BOOL granted, NSError *error) {
 //Handle the response here…
//Note: If you prompt the user, make sure to call the main thread

}];

Since you can only request access once, you’ll need to test for the current authorization status first. We decided to create our own status flags that correspond with Event Kit’s then call authorizationStatus.

/// \brief Proxy for EKAuthorizationStatus in iOS 6
enum SKEKAuthorizationStatus {
    SKEKAuthorizationStatusNotDetermined = 0,
    SKEKAuthorizationStatusRestricted,
    SKEKAuthorizationStatusDenied,
    SKEKAuthorizationStatusAuthorized
};

/// \brief Helper method checks the authorization
/// \return If running in iOS 6 or higher returns the EKAuthorizationStatus; otherwise, returns SKEKAuthorizationStatusAuthorized
- (enum SKEKAuthorizationStatus) authorizationStatus {
    if ([[EKEventStore class] respondsToSelector: @selector(authorizationStatusForEntityType:)]) {
        return [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
    }
    else {
        return SKEKAuthorizationStatusAuthorized;
    }
}

If calendar access was denied before (SKEKAuthorizationStatusDenied), then we prompt the user to enable access by tapping Settings > Privacy > Calendars > Skedi. If permission is undetermined (SKEKAuthorizationStatusNotDetermined), then we instantiate the EKEventStore and request access. If previously granted access, we can safely alloc and init without a care.

So, I hope this helps anyone who is currently working on adapting their Event Kit code for iOS 6. Let me know if you have any feedback.

Advertisements
Handling Access to Calendars in iOS 6

2 thoughts on “Handling Access to Calendars in iOS 6

  1. ifleshdev says:

    Thank you very much, i have a lot of headache with this permissions, but your solution is the most simple and the only what work without pain in the ….

    But don’t forget to use “dispatch_async(dispatch_get_main_queue(), ^{ });” inside of requestAccessToEntityType to use your “self” methods

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s