Archive for 8th October 2012

iOS 6 Calendar and Address Book issues

I’m sure that it was noted somewhere in the docs or change log, but apparently they changed the way that you access the Calendar and Address Book data for iOS 6. Previously, you could just create an event store or address book object and fire away, but now there is an extra step involved.

Now, you have to request access, and then in the callback that fires when access is granted by the user, perform the actions that you need to do with the object.

So here is what the code to access the Calendar looks like:

EKEventStore *eventStore = [[EKEventStore alloc] init];
if ([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)])
{
    [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error)
            {
                // display error message here
            }
            else if (!granted)
            {
                // display access denied error message here
            }
            else
            {
                // access granted
                // do the important stuff here
            }
        });
    }];
}
else
{
    // do the important stuff here
}
 
[eventStore release];

And here is what the code looks like to access the Address Book data:

if ([self isABAddressBookCreateWithOptionsAvailable])
{
    CFErrorRef error = nil;
    addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error)
            {
                // display error message here
            }
            else if (!granted)
            {
                // display access denied error message here
            }
            else
            {
                // access granted
                // do the important stuff here
            }
        });
    });
}
else
{
    addressBook = ABAddressBookCreate();
    // do the important stuff here
}

And in the above code, here is the method that tests for the existence of the ABAddressBookCreateWithOptions function:

- (BOOL)isABAddressBookCreateWithOptionsAvailable
{
    return &ABAddressBookCreateWithOptions != NULL;
}

And also, I am not sure if this is an iOS 6 thing or not, and ultimately I am not sure if it will help in the long run, but in my own testing of generating PDFs on an iOS 6 device, I found that using the Core Foundation function CFAttributedStringSetAttribute was causing intermittent crashes. So I switched to using the function CFAttributedStringSetAttributes instead, and it seemed to work much better. Here is a code sample of what that looks like:

CFMutableDictionaryRef fontDict = CFDictionaryCreateMutable(NULL, 1, NULL, NULL);
CFDictionaryAddValue(fontDict, kCTFontAttributeName, fontRef);
CFAttributedStringSetAttributes(currentText2, CFRangeMake(0, CFAttributedStringGetLength(currentText2)), fontDict, false);
CFRelease(fontDict);

BTW, happy birthday to Chevy Chase, one of the best comic actors ever.