My method of programmatically retrieving e-mail addresses from the Address Book no longer seems to work on iOS 6 devices. It worked in iOS 5 and oddly, still works in the iO
I created a helper class, AddressBookHelper
, to handle backward compatibility. Here are the guts:
-(BOOL)isABAddressBookCreateWithOptionsAvailable {
return &ABAddressBookCreateWithOptions != NULL;
}
-(void)loadContacts {
ABAddressBookRef addressBook;
if ([self isABAddressBookCreateWithOptionsAvailable]) {
CFErrorRef error = nil;
addressBook = ABAddressBookCreateWithOptions(NULL,&error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
// callback can occur in background, address book must be accessed on thread it was created on
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
[self.delegate addressBookHelperError:self];
} else if (!granted) {
[self.delegate addressBookHelperDeniedAcess:self];
} else {
// access granted
AddressBookUpdated(addressBook, nil, self);
CFRelease(addressBook);
}
});
});
} else {
// iOS 4/5
addressBook = ABAddressBookCreate();
AddressBookUpdated(addressBook, NULL, self);
CFRelease(addressBook);
}
}
void AddressBookUpdated(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
AddressBookHelper *helper = (AddressBookHelper *)context;
ABAddressBookRevert(addressBook);
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
// process the contacts to return
NSArray *contacts = ...
[[helper delegate] addressBookHelper:helper finishedLoading:contacts];
};
Probably related to the new privacy controls, as of iOS 6, on the device, an app can’t access the user’s contacts without their permission.
Code:
-(void)addressBookValidation
{
NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults];
ABAddressBookRef addressbook = ABAddressBookCreate();
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL)
{
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressbook, ^(bool granted, CFErrorRef error)
{
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_release(sema);
}
else if(ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
accessGranted = YES;
}
else if (ABAddressBookGetAuthorizationStatus()==kABAuthorizationStatusDenied)
{
accessGranted = NO;
}
else if (ABAddressBookGetAuthorizationStatus()==kABAuthorizationStatusRestricted){
accessGranted = NO;
}
else
{
accessGranted = YES;
}
}
else
{
accessGranted = YES;
}
[prefs setBool:accessGranted forKey:@"addressBook"];
NSLog(@"[prefs boolForKey:@'addressBook']--->%d",[prefs boolForKey:@"addressBook"]);
[prefs synchronize];
CFRelease(addressbook);
}
Probably related to the new privacy controls—as of iOS 6, on the device, an app can’t access the user’s contacts without their permission. From the documentation:
On iOS 6.0 and later, if the caller does not have access to the Address Book database:
• For apps linked against iOS 6.0 and later, this function returns NULL.
• For apps linked against previous version of iOS, this function returns an empty read-only database.
If you haven’t seen the permissions alert come up (“SomeApp would like access to your contacts”), it’s possible that the direct address-book APIs just assume that they don’t have access and silently fail; you might have to display something from the AddressBookUI framework to trigger it.
Try with this: access to the address book must be granted before it can be access programmatically. Here is what I ended up doing.
#import <AddressBookUI/AddressBookUI.h>
// Request authorization to Address Book
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
// First time access has been granted, add the contact
[self _addContactToAddressBook];
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
[self _addContactToAddressBook];
}
else {
// The user has previously denied access
// Send an alert telling user to change privacy setting in settings app
}