I know it is possible to pull up a contact and see information based on one contact. But is there any way to get all the emails from the contacts you have entered email addresses for and then store that in a NSArray?
This is my first time working with contacts so I don't know much about it.
Yes, you can do this. It seems suspicious that you would want to do this (why do you need this information?), but it isn't difficult to do.
You can use ABAddressBookCopyArrayOfAllPeople to get an CFArrayRef with all of the people, and then you can query kABPersonEmailProperty of each using ABRecordCopyValue. The code would look something like this (untested):
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSMutableArray *allEmails = [[NSMutableArray alloc] initWithCapacity:CFArrayGetCount(people)];
for (CFIndex i = 0; i < CFArrayGetCount(people); i++) {
ABRecordRef person = CFArrayGetValueAtIndex(people, i);
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++) {
NSString* email = (NSString*)ABMultiValueCopyValueAtIndex(emails, j);
[allEmails addObject:email];
[email release];
}
CFRelease(emails);
}
CFRelease(addressBook);
CFRelease(people);
(Memory allocation may be a little off; it's been a while since I've developed Cocoa/Core Foundation code.)
But seriously, question why you are doing this. There's a good chance that there's a better solution by just using the Apple-provided APIs to present a contact picker at appropriate times.
ABAddressBookRef allPeople = ABAddressBookCreate();
CFArrayRef allContacts = ABAddressBookCopyArrayOfAllPeople(allPeople);
CFIndex numberOfContacts = ABAddressBookGetPersonCount(allPeople);
NSLog(#"numberOfContacts------------------------------------%ld",numberOfContacts);
for(int i = 0; i < numberOfContacts; i++){
NSString* name = #"";
NSString* phone = #"";
NSString* email = #"";
ABRecordRef aPerson = CFArrayGetValueAtIndex(allContacts, i);
ABMultiValueRef fnameProperty = ABRecordCopyValue(aPerson, kABPersonFirstNameProperty);
ABMultiValueRef lnameProperty = ABRecordCopyValue(aPerson, kABPersonLastNameProperty);
ABMultiValueRef phoneProperty = ABRecordCopyValue(aPerson, kABPersonPhoneProperty);\
ABMultiValueRef emailProperty = ABRecordCopyValue(aPerson, kABPersonEmailProperty);
NSArray *emailArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailProperty);
NSArray *phoneArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(phoneProperty);
if (fnameProperty != nil) {
name = [NSString stringWithFormat:#"%#", fnameProperty];
}
if (lnameProperty != nil) {
name = [name stringByAppendingString:[NSString stringWithFormat:#" %#", lnameProperty]];
}
if ([phoneArray count] > 0) {
if ([phoneArray count] > 1) {
for (int i = 0; i < [phoneArray count]; i++) {
phone = [phone stringByAppendingString:[NSString stringWithFormat:#"%#\n", [phoneArray objectAtIndex:i]]];
}
}else {
phone = [NSString stringWithFormat:#"%#", [phoneArray objectAtIndex:0]];
}
}
if ([emailArray count] > 0) {
if ([emailArray count] > 1) {
for (int i = 0; i < [emailArray count]; i++) {
email = [email stringByAppendingString:[NSString stringWithFormat:#"%#\n", [emailArray objectAtIndex:i]]];
}
}else {
email = [NSString stringWithFormat:#"%#", [emailArray objectAtIndex:0]];
}
}
NSLog(#"NAME : %#",name);
NSLog(#"PHONE: %#",phone);
NSLog(#"EMAIL: %#",email);
NSLog(#"\n");
}
#import AddressBook;
- (void)addressBookInit {
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusDenied || ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusRestricted){
// NSLog(#"Denied");
UIAlertView *cantAddContactAlert = [[UIAlertView alloc] initWithTitle: #"Cannot get contacts" message: #"You must give the app permission to read the contacts first." delegate:nil cancelButtonTitle: #"OK" otherButtonTitles: nil];
[cantAddContactAlert show];
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized){
// NSLog(#"Authorized");
[self getEmails];
} else {
// NSLog(#"Not determined");
ABAddressBookRequestAccessWithCompletion(ABAddressBookCreateWithOptions(NULL, nil), ^(bool granted, CFErrorRef error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!granted){
//4
UIAlertView *cantAddContactAlert = [[UIAlertView alloc] initWithTitle: #"Cannot get contacts" message: #"You must give the app permission to read the contacts first." delegate:nil cancelButtonTitle: #"OK" otherButtonTitles: nil];
[cantAddContactAlert show];
return;
}
// NSLog(#"Authorized 2");
[self getEmails];
});
});
}
}
-(NSArray *)getEmails
{
NSMutableArray *emails = [NSMutableArray array];
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil);
NSArray *allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBookRef);
for (id record in allContacts)
{
ABRecordRef person = (__bridge ABRecordRef)record;
ABMultiValueRef emailProperty = ABRecordCopyValue(person, kABPersonEmailProperty) ;
NSArray *personEmails = (__bridge_transfer NSArray *)ABMultiValueCopyArrayOfAllValues(emailProperty);
[emails addObjectsFromArray:personEmails];
CFRelease(person);
CFRelease(emailProperty);
}
CFRelease(addressBookRef) ;
for (NSString *email in emails)
{
NSLog(#"%#", email) ;
}
return emails;
}
for iOS 9+, use Contacts framework, Objective C
-(NSArray*)getAllContacts{
__block NSMutableArray *allContacts = nil;
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactEmailAddressesKey, CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
allContacts = [NSMutableArray array];
for (CNContact *contact in cnContacts) {
// copy data to my custom Contacts class.
// create custom class Contacts with firstName,lastName,image and emailAddress
for (CNLabeledValue<NSString*> *email in contact.emailAddresses) {
Contact *newContact = [[Contact alloc] init];
newContact.firstName = contact.givenName;
newContact.lastName = contact.familyName;
UIImage *image = [UIImage imageWithData:contact.imageData];
newContact.image = image;
newContact.emailAddress = email.value;
[allContacts addObject:newContact];
}
}
}
}
}];
return allContacts;}
Related
I accessing contacts and sending it to server, my question is do I have any possibility of detecting which country contact belongs to?
Thank you.
Follow the steps below.
1 : Fetch the phone numbers from device.
2 : You need to find the country code from the phone number. Phone numbers can be saved in the device in different formats. International format, local format, with country code, without country code etc. So you need to consider all these cases to split the country code from the phone number. The following code may help you to get the country code from the phone number.
- (NSString *)getDiallingCodeFromPhoneNumber:(NSString *)phoneNumber
{
NSString *countryCode = #"not found";
NSString *code;
NSString *dialledNumber = [[phoneNumber componentsSeparatedByCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:#"-() "]]
componentsJoinedByString:#""];
NSString *interNationalCode = [dialledNumber substringToIndex:2];
NSArray *allCodes = [self.diallingCodesDictionary allValues];
int idx;
if([dialledNumber hasPrefix:#"+"])
{
dialledNumber = [dialledNumber substringFromIndex:1];
}
else if([interNationalCode isEqualToString:#"00"])
{
dialledNumber = [dialledNumber substringFromIndex:2];
}
for (idx = 1 ; idx < dialledNumber.length; idx++) {
code = [dialledNumber substringToIndex:idx];
if([allCodes containsObject:code])
{
countryCode = code;
break;
}
}
return countryCode;
}
3 : You will get the list of country codes and country name from internet. Add it as a plist in your bundle. (I took this plist from a third part, HMDiallingCode)
4 : Now you will get the country name corresponding to your country code from that plist.
5 : If you got countryCode = not found, it means that the phone number is not saved with country code. This makes it clear that, that particular phone number is a local number. So in this case you can select the country name from NSLocale.
Try this code function you can get all of information would you like.
+(NSArray *)getAllContacts
{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
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);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
NSLog(#"Fetching contact info ----> ");
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
CFIndex nPeople = CFArrayGetCount(allPeople);
NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
for (int i = 0; i < nPeople; i++)
{
ContactDetailModel *contacts = [[ContactDetailModel alloc] init]; // it is NsObject class. this is contained variables and array which required for get contact information. It is not necessary for you. you can maintain according your requirments.
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
if((__bridge NSString*)ABRecordCopyCompositeName(person)){
contacts.compse_name = (__bridge NSString*)ABRecordCopyCompositeName(person);
NSLog(#"compse_name = %#",contacts.compse_name);
}
if (!contacts.compse_name) {
contacts.compse_name = #"";
}
//get First Name and Last Name
if((__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty)){
contacts.first_name = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
}
if((__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty)){
contacts.last_name = (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
}
if (!contacts.first_name) {
contacts.first_name = #"";
}
if (!contacts.last_name) {
contacts.last_name = #"";
}
NSLog(#"fname and lname = %# %#",contacts.first_name,contacts.last_name);
/// URL
ABMultiValueRef webpages = ABRecordCopyValue(person, kABPersonURLProperty);
NSString* homepage;
// Then iterate thru webpages to get the homepage
for (CFIndex k=0; k < ABMultiValueGetCount(webpages); k++)
{
homepage = (__bridge NSString*)ABMultiValueCopyValueAtIndex(webpages, k);
NSLog(#"homepage = %#",homepage);
}
NSLog(#"URL = %#",homepage);
//// get BirthDay
if((__bridge NSString*)ABRecordCopyValue(person, kABPersonBirthdayProperty)){
contacts.birthday = (__bridge NSString*)ABRecordCopyValue(person, kABPersonBirthdayProperty);
}
if (!contacts.birthday) {
contacts.birthday = #"";
}
//// get Company Name
if((__bridge NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty)){
contacts.company = (__bridge NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty);
}
if (!contacts.company) {
contacts.company = #"";
}
// get contacts picture, if pic doesn't exists, show standart one
contacts.img_data = (__bridge NSData *)ABPersonCopyImageData(person);
if (!contacts.img_data) {
UIImage *image = [UIImage imageNamed:#"profile#2x.png"];
NSData *img_data = UIImagePNGRepresentation(image);
contacts.img_data = img_data;
}
//get Phone Numbers
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
NSString * strippedNumber = [phoneNumber stringByReplacingOccurrencesOfString:#"[^0-9]" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0, [phoneNumber length])];
[phoneNumbers addObject:strippedNumber];
//NSLog(#"All numbers %#", phoneNumbers);
}
contacts.arrCallIDs = phoneNumbers;
/// get Addresss
NSMutableArray *arry_address = [[NSMutableArray alloc] init];
ABMutableMultiValueRef multiAddress = ABRecordCopyValue(person, kABPersonAddressProperty);
for(CFIndex i=0; i<ABMultiValueGetCount(multiAddress);i++){
CFDictionaryRef address = ABMultiValueCopyValueAtIndex(multiAddress, i);
NSString *street = (NSString*) CFDictionaryGetValue(address, kABPersonAddressStreetKey);
NSString *city = (NSString*) CFDictionaryGetValue(address, kABPersonAddressCityKey);
NSString *state = (NSString*) CFDictionaryGetValue(address, kABPersonAddressStateKey);
NSString *postal = (NSString*) CFDictionaryGetValue(address, kABPersonAddressZIPKey);
NSString *country = (NSString*) CFDictionaryGetValue(address, kABPersonAddressCountryKey);
NSString *country_id = (NSString*) CFDictionaryGetValue(address, kABPersonAddressCountryCodeKey);
NSMutableDictionary *add_field = [[NSMutableDictionary alloc] init];
[add_field setValue:street forKey:#"street"];
[add_field setValue:city forKey:#"city"];
[add_field setValue:state forKey:#"state"];
[add_field setValue:postal forKey:#"postal"];
[add_field setValue:country forKey:#"country"];
[add_field setValue:country_id forKey:#"country_id"];
// NSLog(#"Address = %#",add_field);
[arry_address addObject:add_field];
}
contacts.arrAddress = arry_address;
//get Contact email
NSMutableArray *contactEmails = [NSMutableArray new];
ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
NSString *contactEmail = (__bridge NSString *)contactEmailRef;
[contactEmails addObject:contactEmail];
// NSLog(#"All emails are:%#", contactEmails);
}
contacts.arrEmails = contactEmails;
[items addObject:contacts];
//NSLog(#"Person is: %#", contacts.firstNames);
//NSLog(#"Phones are: %#", contacts.numbers);
//NSLog(#"Email is:%#", contacts.emails);
}
return items;
} else {
NSLog(#"Cannot fetch Contacts :( ");
return NO;
}
}
I have problems with the threads at the recorer for, I have a contact list of 600 and 6 shows me the following error.
Thread 1: EXC_BAD_ACCESS (code = 1, address = 0x29)
is the following code
-(void) actualizarContactos
{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
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);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
//ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
// NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
NSMutableArray *TodosContactos = [[NSMutableArray alloc]init];
//consultar numero de contactos anteriores
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *numeroContactos = [userDefaults objectForKey:#"numeroContactos"];
int numContactos = [numeroContactos intValue];
//validar si hay contactos nuevos
if(numContactos != nPeople)
{
for (int i = 0; i < nPeople; i++)
{
// NSMutableArray *contacto = [[NSMutableArray alloc]init];
ContactsData *contacts = [ContactsData new];
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
//get First Name and Last Name
// NSMutableArray *name = [[NSMutableArray alloc]init];
if((__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty))
{
contacts.firstName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
}
if((__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty))
{
contacts.lastName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
}
if (!contacts.firstName) {
contacts.firstName = #"";
}
if (!contacts.lastName) {
contacts.lastName = #"";
}
contacts.compositeName = [NSString stringWithFormat:#"%# %#",contacts.firstName,contacts.lastName];
// get contacts picture, if pic doesn't exists, show standart one
Boolean sw = true;
NSData *imgData = (__bridge_transfer NSData *)ABPersonCopyImageData(person);
contacts.photo = [UIImage imageWithData:imgData];
if (!contacts.photo) {
sw = false;
contacts.photo = [UIImage imageNamed:#"contacts-ico#2x.png"];
}
//get Phone Numbers
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
Boolean swContactoSiguiente = true;
ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge_transfer NSString *) phoneNumberRef;
//prueba
// NSLog([NSString stringWithFormat:#"name: %# tel: %#",contacts.compositeName,phoneNumbers]);
if(![phoneNumber hasPrefix:#"+"] && ![phoneNumber hasPrefix:#"00"] && ![phoneNumber hasPrefix:#"011"])
{
swContactoSiguiente = true;
}
else
{
swContactoSiguiente = false;
[phoneNumbers addObject:phoneNumber];
}
}
if(swContactoSiguiente)
{
continue;
}
contacts.phones = phoneNumbers;
//get Contact email
NSMutableArray *contactEmails = [NSMutableArray new];
ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
NSString *contactEmail = (__bridge_transfer NSString *)contactEmailRef;
[contactEmails addObject:contactEmail];
// NSLog(#"All emails are:%#", contactEmails);
}
// [contacts setEmails:contactEmails];
contacts.emails = contactEmails;
//guardar en CoreData
if(contacts.phones.count != 0)
{
contacts.phone = [self deleteSpace:contacts.phones[0]];
}
//se valida existencia del phone en la base de datos
if([self consultarTelefono:contacts.phone])
{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *newContact;
newContact = [NSEntityDescription insertNewObjectForEntityForName:#"Contacts" inManagedObjectContext:context];
[newContact setValue: contacts.compositeName forKey:#"compositeName"];
[newContact setValue: contacts.firstName forKey:#"firstName"];
[newContact setValue: contacts.lastName forKey:#"lastName"];
[newContact setValue: contacts.phone forKey:#"phone"];
NSNumber *fv = [NSNumber numberWithBool:false];
[newContact setValue:fv forKey:#"favorite"];
if(sw)
{
[newContact setValue: imgData forKey:#"photo"];
}
NSError *error;
[context save:&error];
// [items addObject:contacts];
}
//ABRecordRef
// CFRelease(addressBook2);
// CFRelease(person);
// CFRelease(source2);
// CFRelease(allPeople2);
// NSLog([NSString stringWithFormat:#"%d",i]);
}
// se guarda en memoria numero de contactos
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSString stringWithFormat:#"%d",(int)nPeople] forKey:#"numeroContactos"];
[defaults synchronize];
}
}
else
{
UIAlertView *alertFailSave = [[UIAlertView alloc] initWithTitle:#"Error"
message:NSLocalizedString(#"TEXT_ACCESS", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(#"LO_BUTTON_OK", nil)
otherButtonTitles:nil];
[alertFailSave show];
}
}
la corrección fue cambiar el siguiente codigo:
// ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
// ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
// CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
// CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
// NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
por este.
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
Phone number getting like this.
Phone ABMultiValueRef 0x17674380 with 1 value(s)
0: $!!$ (0x176740e0) - 7124779070 (0x176742a0)
How to get this number"7124779070" from the above line.
I'm using this code for ios 7.Is it correct or wrong ,Please sugggest me.
int i;
ABAddressBookRef contactBook = ABAddressBookCreateWithOptions(NULL, NULL);
NSMutableArray *allData = ( NSMutableArray *)(ABAddressBookCopyArrayOfAllPeople(contactBook));
CFIndex contactNum = CFArrayGetCount((__bridge CFArrayRef)(allData));
for (i = 0; i < contactNum; i++)
{
ABRecordRef ref = CFArrayGetValueAtIndex((__bridge CFMutableArrayRef)(allData), i);
NSString* firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
NSString* lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
NSString* phonesNum = ABRecordCopyValue(ref, kABPersonPhoneProperty);
// Remove all formatting symbols that might be in both phone number being compared
NSCharacterSet *toExclude = [NSCharacterSet characterSetWithCharactersInString:#"/.()- "];
phonesNum = [[phonesNum componentsSeparatedByCharactersInSet:toExclude] componentsJoinedByString: #""];
NSString *phoneNumber = [[phonesNum componentsSeparatedByCharactersInSet:toExclude] componentsJoinedByString: #""];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
if (firstName!=nil)
{
[dic setObject:(__bridge id)(firstName) forKey:#"firstName"];
}
if (lastName !=nil) {
[dic setObject:(__bridge id)(lastName) forKey:#"lastName"];
}
if (phonesNum!=nil) {
[dic setObject:(__bridge id)(phonesNum) forKey:#"phonesNum"];
}
[arr_Contacts addObject:dic];
NSLog(#"First name %#", firstName);
NSLog(#"Last Name %#", lastName);
NSLog(#"Phone %#", phonesNum);
}
First, request permission:
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status != kABAuthorizationStatusAuthorized && status != kABAuthorizationStatusNotDetermined) {
// tell user to enable contacts in privacy settings
NSLog(#"You previously denied access: You must enable access to contacts in settings");
return;
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (!addressBook) {
NSLog(#"ABAddressBookCreateWithOptions error: %#", CFBridgingRelease(error));
return;
}
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (error) {
NSLog(#"ABAddressBookRequestAccessWithCompletion error: %#", CFBridgingRelease(error));
}
if (granted) {
[self getContacts:addressBook];
} else {
// tell user to enable contacts in privacy settings
NSLog(#"You just denied access: You must enable access to contacts in settings");
}
CFRelease(addressBook);
});
Second, to retrieve the phone numbers, use ABMultiValueCopyValueAtIndex:
- (void)getContacts:(ABAddressBookRef)addressBook
{
NSArray *allData = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
NSInteger contactCount = [allData count];
for (int i = 0; i < contactCount; i++) {
ABRecordRef person = CFArrayGetValueAtIndex((__bridge CFArrayRef)allData, i);
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
if (firstName) {
dictionary[#"firstName"] = firstName;
}
if (lastName) {
dictionary[#"lastName"] = lastName;
}
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phoneNumberCount = ABMultiValueGetCount(phones);
if (phoneNumberCount > 0) {
NSString *phone = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, 0));
dictionary[#"phone"] = phone;
}
// or if you wanted to iterate through all of them, you could do something like:
//
// for (int j = 0; j < phoneNumberCount; j++) {
// NSString *phone = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, j));
//
// // do something with `phone`
// }
if (phones) {
CFRelease(phones);
}
[arr_Contacts addObject:dictionary];
}
}
A couple of additional issues addressed above:
The ABAddressBookCreateWithOptions does not return a mutable array. It's an immutable array. Replace all of those mutable references with immutable.
You must honor the Create Rule, namely that you're responsible for releasing any object returned from a Core Foundation method with either Create or Copy in its name. If the object supports toll-free bridging (e.g. the array of contacts, the first name string, the last name string, etc.), you can transfer ownership to ARC with CFBridgingRelease or __bridge_transfer. If the object doesn't support toll-free bridging (such as the phones or addressBook objects, above), then you must explicitly call CFRelease for the object in question.
Make sure to run your code through the static analyzer (shift+command+B, or choose "Analyze" from Xcode's "Product" menu), and it will identify these sorts of issues for you.
If a function, such as ABAddressBookCreateWithOptions offers an error parameter, you should avail yourself of it. I illustrate the proper use of the CFErrorRef object above.
What do you recive in console from Phone %# NSLog ? if Phone ABMultiValueRef 0x17674380 with 1 value(s) 0: $!!$ (0x176740e0) - 7124779070 (0x176742a0)just substring after '-'
NSString *myString = #"Phone ABMultiValueRef 0x17674380 with 1 value(s) 0: $!!$ (0x176740e0) - 7124779070 (0x176742a0)";
NSArray *myArray = [myString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"-"]];
and this is my method to get phone's
- (void) getContacts
{
NSMutableDictionary *response = [[NSMutableDictionary alloc] init];
ABAddressBookRef contactBook = ABAddressBookCreateWithOptions(NULL, NULL);
arr_Contacts = [[NSMutableArray alloc] init];
ABAddressBookRef allPeople = contactBook;
CFArrayRef allContacts = ABAddressBookCopyArrayOfAllPeople(allPeople);
CFIndex numberOfContacts = ABAddressBookGetPersonCount(allPeople);
NSLog(#"contact == %#",allContacts);
NSLog(#"numberOfContacts------------------------------------%ld",numberOfContacts);
for(int i = 0; i < numberOfContacts; i++){
NSString* name = #"";
NSString* phone = #"";
NSString* email = #"";
ABRecordRef aPerson = CFArrayGetValueAtIndex(allContacts, i);
ABMultiValueRef fnameProperty = ABRecordCopyValue(aPerson, kABPersonFirstNameProperty);
ABMultiValueRef lnameProperty = ABRecordCopyValue(aPerson, kABPersonLastNameProperty);
ABMultiValueRef phoneProperty = ABRecordCopyValue(aPerson, kABPersonPhoneProperty);\
ABMultiValueRef emailProperty = ABRecordCopyValue(aPerson, kABPersonEmailProperty);
NSArray *emailArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailProperty);
NSArray *phoneArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(phoneProperty);
if (fnameProperty != nil) {
name = [NSString stringWithFormat:#"%#", fnameProperty];
}
if (lnameProperty != nil) {
name = [name stringByAppendingString:[NSString stringWithFormat:#" %#", lnameProperty]];
}
if ([phoneArray count] > 0) {
if ([phoneArray count] > 1) {
for (int i = 0; i < [phoneArray count]; i++) {
phone = [phone stringByAppendingString:[NSString stringWithFormat:#"%#, ", [phoneArray objectAtIndex:i]]];
}
}else {
phone = [NSString stringWithFormat:#"%#", [phoneArray objectAtIndex:0]];
}
}
if ([emailArray count] > 0) {
if ([emailArray count] > 1) {
for (int i = 0; i < [emailArray count]; i++) {
email = [email stringByAppendingString:[NSString stringWithFormat:#"%#\n", [emailArray objectAtIndex:i]]];
}
}else {
email = [NSString stringWithFormat:#"%#", [emailArray objectAtIndex:0]];
}
}
NSLog(#"NAME : %#",name);
NSLog(#"PHONE: %#",phone);
NSLog(#"EMAIL: %#",email);
NSLog(#"\n");
[response setObject:name forKey:#"name"];
[response setObject:phone forKey:#"phone"];
[response setObject:email forKey:#"email"];
[arr_Contacts addObject:response];
}
}
Cheers
when i am syncing facebook contact in my iphone contact then my app crash in getting all phone contact. App crashed everytime on first name giving bad access. and app work fine if facebook friends is not synced .Here is my code:
+(NSMutableArray *)getAllContacts
{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
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);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted)
{
#ifdef DEBUG
NSLog(#"Fetching contact info ----> ");
#endif
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
for (int i = 0; i < nPeople; i++)
{
NSMutableDictionary *contacts = [NSMutableDictionary new];
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
//get First Name and Last Name
NSString *firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *name=#"";
if ([firstName length]>0 && [lastName length]>0)
name= [NSString stringWithFormat:#"%# %#",firstName,lastName];
else if ([firstName length]>0 && [lastName length]==0)
name= [NSString stringWithFormat:#"%#",firstName];
else if ([firstName length]==0 && [lastName length]>0)
name= [NSString stringWithFormat:#"%#",lastName];
else
name= #"No Name";
contacts[#"name"]=name;
// get contacts picture, if pic doesn't exists, show standart one
NSData *imgData = (__bridge NSData *)ABPersonCopyImageData(person);
UIImage *image= [UIImage imageWithData:imgData];
if (!image)
image = [UIImage imageNamed:#"profilebase_small.png"];
contacts[#"image"]=image;
//get Phone Numbers
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
[phoneNumbers addObject:phoneNumber];
}
contacts[#"numbers"]=phoneNumbers;
//get Contact email
NSMutableArray *contactEmails = [NSMutableArray new];
ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
NSString *contactEmail = (__bridge NSString *)contactEmailRef;
[contactEmails addObject:contactEmail];
// NSLog(#"All emails are:%#", contactEmails);
}
contacts[#"emails"]=contactEmails;
[items addObject:contacts];
}
return items;
} else
{
#ifdef DEBUG
NSLog(#"Cannot fetch Contacts :( ");
#endif
return NO;
}
}
Replace this line CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); with CFIndex nPeople = CFArrayGetCount(allPeople);
I have the following method for getting the AddressBook contacts:
- (void) scanAddressBook
{
NSUInteger i;
NSUInteger k;
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *people = (__bridge_transfer NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook);
if ( people==nil )
{
NSLog(#"NO ADDRESS BOOK ENTRIES TO SCAN");
CFRelease(addressBook);
return;
}
for ( i=0; i<[people count]; i++ )
{
ABRecordRef person = (__bridge ABRecordRef)[people objectAtIndex:i];
NSNumber *recordID = [NSNumber numberWithUnsignedInt:ABRecordGetRecordID(person)];
ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString *name = [NSString stringWithFormat:#"%# %#",
(__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty),
(__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty)];
CFIndex phoneNumberCount = ABMultiValueGetCount( phoneNumbers );
NSMutableArray *arrPhoneNumbers = [[NSMutableArray alloc] initWithCapacity:phoneNumberCount];
for ( k=0; k<phoneNumberCount; k++ )
{
CFStringRef phoneNumberLabel = ABMultiValueCopyLabelAtIndex( phoneNumbers, k );
NSString *phoneNumberValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex( phoneNumbers, k );
CFStringRef phoneNumberLocalizedLabel = ABAddressBookCopyLocalizedLabel( phoneNumberLabel );
[arrPhoneNumbers addObject:phoneNumberValue];
CFRelease(phoneNumberLocalizedLabel);
CFRelease(phoneNumberLabel);
}
NSMutableDictionary *dictPerson = [[NSMutableDictionary alloc] init];
[dictPerson setObject:name forKey:#"contactName"];
[dictPerson setObject:arrPhoneNumbers forKey:#"phoneNumbers"];
[dictPerson setObject:recordID forKey:#"recordID"];
[arrABFriends addObject:dictPerson];
}
CFRelease(addressBook);
}
Later on, in the next view, I have an option to delete the selected record & this is how it looks like:
-(IBAction) removeContactFromAB
{
ABAddressBookRef addressBook;
CFErrorRef error = NULL;
addressBook = ABAddressBookCreate(); //
CFRetain(addressBook);
ABRecordID recordID = (ABRecordID)[[personToDump objectForKey:#"recordID"] integerValue];
NSLog(#"recordID: %d", recordID);
// ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook,(ABRecordID)recordID);
ABRecordRef person = ABAddressBookGetGroupWithRecordID(addressBook, recordID);
//fullName.text = (NSString *)ABRecordCopyCompositeName((ABRecordRef)person);
ABAddressBookRemoveRecord( addressBook, person, &error );
if(error !=NULL)
{
UIAlertView *alert =[[UIAlertView alloc] initWithTitle:#"error" message:#"deleting" delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK",nil];
[alert show];
}
ABAddressBookSave(addressBook, &error);
NSLog(#"ERROR: %#", &error);
CFRelease(addressBook);
}
I tried to pass the ABRecordRef & ABRecordID to the next view but in both cases I had EXC_BAD_ACCESS on ABAddressBookRemoveRecord( addressBook, person, &error ).
Did your ABAddressBookGetGroupWithRecordID(addressBook, recordID) return something other than null?
I'm having the same problem, i think and the problem is somewhere around the conversation of the recordID's.
If you try
NSNumber *recordID=[NSNumber numberWithUnsignedInt:ABRecordGetRecordID(person)];
ABRecordID recordID2 =(ABRecordID) recordID2;
ABAddressBookGetGroupWithRecordID(addressBook, recordID2)
it's going to return null as well.
I'm not sure how to solve this yet.
ui.: I wanted to add this in comment but turns out i dont have enough rep yet:(
The problem was that I was trying to retrieve the reference from a group with an ID from a reference & I was getting nil as a reference & later trying to find the record with the reference nil. That's where my App was giving EXC_BAD_ACCESS.
So instead of:
ABRecordRef person = ABAddressBookGetGroupWithRecordID(addressBook, recordID);
There should be:
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, recordID);