Retrieve all contacts phone numbers in iOS
So far I saw methods to get multiple phone numbers if I show a picker so user can select people and then get the phone number. What I want is retrieving all contacts' numbers. Is it even possible?
Solution 1:
Try this it works for iOS 6 as well as iOS 5.0 or older:
Sample Project Demo
First add the following frameworks in Link Binary With Libraries
- AddressBookUI.framework
- AddressBook.framework
Then Import
#import <AddressBook/ABAddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
Then use the following code
Requesting permission to access address book
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
__block BOOL accessGranted = NO;
if (&ABAddressBookRequestAccessWithCompletion != NULL) { // We are on iOS 6
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(semaphore);
}
else { // We are on iOS 5 or Older
accessGranted = YES;
[self getContactsWithAddressBook:addressBook];
}
if (accessGranted) {
[self getContactsWithAddressBook:addressBook];
}
Retrieving contacts from addressbook
// Get the contacts.
- (void)getContactsWithAddressBook:(ABAddressBookRef )addressBook {
contactList = [[NSMutableArray alloc] init];
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for (int i=0;i < nPeople;i++) {
NSMutableDictionary *dOfPerson=[NSMutableDictionary dictionary];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
//For username and surname
ABMultiValueRef phones =(__bridge ABMultiValueRef)((__bridge NSString*)ABRecordCopyValue(ref, kABPersonPhoneProperty));
CFStringRef firstName, lastName;
firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
[dOfPerson setObject:[NSString stringWithFormat:@"%@ %@", firstName, lastName] forKey:@"name"];
//For Email ids
ABMutableMultiValueRef eMail = ABRecordCopyValue(ref, kABPersonEmailProperty);
if(ABMultiValueGetCount(eMail) > 0) {
[dOfPerson setObject:(__bridge NSString *)ABMultiValueCopyValueAtIndex(eMail, 0) forKey:@"email"];
}
//For Phone number
NSString* mobileLabel;
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++) {
mobileLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(phones, j);
if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
{
[dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, j) forKey:@"phone"];
}
else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel])
{
[dOfPerson setObject:(__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, j) forKey:@"phone"];
break ;
}
}
[contactList addObject:dOfPerson];
}
NSLog(@"Contacts = %@",contactList);
}
To retrive other information
// All Personal Information Properties
kABPersonFirstNameProperty; // First name - kABStringPropertyType
kABPersonLastNameProperty; // Last name - kABStringPropertyType
kABPersonMiddleNameProperty; // Middle name - kABStringPropertyType
kABPersonPrefixProperty; // Prefix ("Sir" "Duke" "General") - kABStringPropertyType
kABPersonSuffixProperty; // Suffix ("Jr." "Sr." "III") - kABStringPropertyType
kABPersonNicknameProperty; // Nickname - kABStringPropertyType
kABPersonFirstNamePhoneticProperty; // First name Phonetic - kABStringPropertyType
kABPersonLastNamePhoneticProperty; // Last name Phonetic - kABStringPropertyType
kABPersonMiddleNamePhoneticProperty; // Middle name Phonetic - kABStringPropertyType
kABPersonOrganizationProperty; // Company name - kABStringPropertyType
kABPersonJobTitleProperty; // Job Title - kABStringPropertyType
kABPersonDepartmentProperty; // Department name - kABStringPropertyType
kABPersonEmailProperty; // Email(s) - kABMultiStringPropertyType
kABPersonBirthdayProperty; // Birthday associated with this person - kABDateTimePropertyType
kABPersonNoteProperty; // Note - kABStringPropertyType
kABPersonCreationDateProperty; // Creation Date (when first saved)
kABPersonModificationDateProperty; // Last saved date
// All Address Information Properties
kABPersonAddressProperty; // Street address - kABMultiDictionaryPropertyType
kABPersonAddressStreetKey;
kABPersonAddressCityKey;
kABPersonAddressStateKey;
kABPersonAddressZIPKey;
kABPersonAddressCountryKey;
kABPersonAddressCountryCodeKey;
Further Reference Read Apple Docs
UPDATE:
You need to add description about why you need to access the contacts in you Apps-Info.plist
Privacy - Contacts Usage Description
OR
<key>NSContactsUsageDescription</key>
<string>Write the reason why your app needs the contact.</string>
For getting the user image.
UIImage *contactImage;
if(ABPersonHasImageData(ref)){
contactImage = [UIImage imageWithData:(__bridge NSData *)ABPersonCopyImageData(ref)];
}
NOTE:
The AddressBook framework is deprecated in iOS 9
and replaced with the new and improved Contacts Framework
Solution 2:
- AddressBookUI.framework
-
AddressBook.framework
These 2 frameworks are deprecated in iOS 9
---> Apple introduced
- Contact Framework
- ContactUI Framework
Here is uploaded Code using latest frameworks.
Solution 3:
Get permission to the address book or notify the user that the need to change the permission in their settings.
CGFloat iOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if(iOSVersion >= 6.0) {
// Request authorization to Address Book
addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
//start importing contacts
if(addressBookRef) CFRelease(addressBookRef);
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
//start importing contacts
if(addressBookRef) CFRelease(addressBookRef);
}
else {
// The user has previously denied access
// Send an alert telling user to change privacy setting in settings app
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unable to Access" message:@"Grant us access now!" delegate:self cancelButtonTitle:@"Not Now" otherButtonTitles:@"I'll Do It!", nil];
[alert show];
if(addressBookRef) CFRelease(addressBookRef);
}
} else {
addressBookRef = ABAddressBookCreate();
//start importing contacts
if(addressBookRef) CFRelease(addressBookRef);
}
Get the records
CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSArray *contacts = (__bridge NSArray*)records;
CFRelease(records);
for(int i = 0; i < contacts.count; i++) {
ABRecordRef record = (__bridge ABRecordRef)[contacts objectAtIndex:i];
}
Get the phone number
ABMultiValueRef phonesRef = ABRecordCopyValue(recordRef, kABPersonPhoneProperty);
if(phonesRef) {
count = ABMultiValueGetCount(phonesRef);
for(int ix = 0; ix < count; ix++){
CFStringRef typeTmp = ABMultiValueCopyLabelAtIndex(phonesRef, ix);
CFStringRef numberRef = ABMultiValueCopyValueAtIndex(phonesRef, ix);
CFStringRef typeRef = ABAddressBookCopyLocalizedLabel(typeTmp);
NSString *phoneNumber = (__bridge NSString *)numberRef;
NSString *phoneType = (__bridge NSString *)typeRef;
if(typeTmp) CFRelease(typeTmp);
if(numberRef) CFRelease(numberRef);
if(typeRef) CFRelease(typeRef);
}
CFRelease(phonesRef);
}
Keep in mind, some people have 20,000 contacts in their phone. If you plan on doing this, you'll probably have to multithread the process.
Solution 4:
Sure you can. First you'll need to get the user permission for doing so. If you won't the user will have to manually authorize your app from the settings. There's a great example on how to retrieve all phone numbers, names, addresses etc' here.