I'm trying to NSLog name and number from my contact in Address Book.
I succeed to log the name, but I don't succeed to solve the problem with number.
Here is my code :
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
if (addressBook != NULL) {
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (granted) {
CFArrayRef allNames = ABAddressBookCopyArrayOfAllPeople(addressBook);
if (allNames != NULL) {
NSMutableArray *names = [NSMutableArray array];
for (int i = 0; i < CFArrayGetCount(allNames); i++) {
ABRecordRef group = CFArrayGetValueAtIndex(allNames, i);
CFStringRef name = ABRecordCopyCompositeName(group);
[names addObject:(__bridge NSString *)name];
CFRelease(name);
}
NSLog(#"names = %#", names);
CFRelease(allNames);
}
}
CFRelease(addressBook);
});
}
Maybe I have to create NSDictionnary ? I don't know how to solve it...
The phone numbers are a ABMultiValueRef:
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (phones != NULL) {
for (NSInteger index = 0; index < ABMultiValueGetCount(phones); index++) {
NSString *phone = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, index));
NSString *label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phones, index)); // either kABHomeLabel or kABPersonPhoneMainLabel or ...
// do something with `phone` and `label`
}
CFRelease(phones);
}
You'll need to use ABRecordCopyValue(group, kABPersonPhoneProperty) which returns ABMultiValueRef. See https://stackoverflow.com/a/286281/171089 for more.
Related
I am new in IOS Programming. In my simple app I am storing first name,last name and phone number in NSMutableArray.I have a UITextfield where I get the phone number.I wanna search first name and last name according to mobile number.I am storing firstname, lastname and phone number in different Mutable arrays so how to search firstname and lastname in stored array.
This is my code
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
_firstname = [[NSMutableArray alloc]init];
_lastname = [[NSMutableArray alloc]init];
_number = [[NSMutableArray alloc]init];
_fullname = [[NSMutableArray alloc]init];
_arrContacts = [[NSMutableArray alloc]init];
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
ABAddressBookRef addressBook = ABAddressBookCreate( );
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
if (firstName != nil) {
[_firstname addObject:firstName];
}
else{
[_firstname addObject:#"Not Found"];
}
if (lastName != nil) {
[_lastname addObject:lastName];
}
else{
[_lastname addObject:#"Not Found"];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
[[UIDevice currentDevice] name];
NSArray *numbers = (__bridge NSArray *)(ABMultiValueCopyValueAtIndex(phoneNumbers, 0));
if (numbers != nil) {
[_arrContacts addObject:numbers];
NSLog(#"Numbers:%#",_arrContacts);
}
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
_addressBookNum = [_addressBookNum stringByAppendingFormat: #":%#",phoneNumber];
}
}
// NSLog(#"AllNumber:%#",_addressBookNum);
}
else {
// Send an alert telling user to change privacy setting in settings app
}
CFRelease(addressBookRef);
NSLog(#"This is Name: %#",_firstname);
NSLog(#"This is LastName: %#",_lastname);
NSLog(#"Number: %#",_arrContacts);
}
Please suggest some idea to do this
Instead of saving name last name and number in different array store it in single array with dictionary. Suppose NSMutabelArray *details
create dictionary having three values name lastname and number, and add this dictoianry into array,
so it will be easy for you to further use
I am developing an app in which i have to save contact in address book, but if the the contact is already saved in contact then it should not save.
But i have no idea is it possible to check a contact whether it is exits in contact list of iPhone or not?
Any help would be appreciated.
Thanks in advance.
Solved issue
-(void)CheckContactIsExits{
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
NSArray *allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
ABRecordRef pet = ABPersonCreate();
ABRecordSetValue(pet, kABPersonFirstNameProperty, (__bridge CFStringRef)#"VoxSci Activation", nil);
for (id record in allContacts){
ABRecordRef thisContact = (__bridge ABRecordRef)record;
if (CFStringCompare(ABRecordCopyCompositeName(thisContact),
ABRecordCopyCompositeName(pet), 0) == kCFCompareEqualTo){
NSLog(#"The contact already exists");
//The contact already exists!
isContactExits=YES;
}
}
}
Assuming your using Apples framework for this your user will be given the option to "create new contact" or if its already in the contacts list "add to existing contact". Therefore the user can decide if it should be added or not
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
And read all the contacts in iPhone and check the name or phone exit or not.
Check Contact is Exit or Not By Contact Number
Note : Only replace checkingPhoneNumber variable by your checking contact number
ABAddressBookRef * addressbook = ABAddressBookCreateWithOptions(Nil, Nil);
NSArray *people = (__bridge NSArray*)ABAddressBookCopyArrayOfAllPeople(addressbook);
NSMutableArray *phoneArray=[[NSMutableArray alloc] init];
for(id person in people)
{
// get person contact number
ABMultiValueRef phones = (ABMultiValueRef)ABRecordCopyValue((__bridge ABRecordRef)(person), kABPersonPhoneProperty);
NSString* mobile=#"";
NSString* mobileLabel;
for (int i=0; i < ABMultiValueGetCount(phones); i++)
{
mobileLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel]) {
NSLog(#"mobile:");
} else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel]) {
NSLog(#"iphone:");
} else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhonePagerLabel]) {
NSLog(#"pager:");
}
mobile = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(#"%#", mobile);
// remove all spaces bracket from contact number
NSMutableString *newPhoneStr = [[NSMutableString alloc] init];;
int j = [mobile length];
for (int i=0; i<j; i++)
{
if ([mobile characterAtIndex:i] >=48 && [mobile characterAtIndex:i] <=59)
{
[newPhoneStr appendFormat:#"%c",[mobile characterAtIndex:i]];
}
}
//add contact into phoneArray
[phoneArray addObject:newPhoneStr];
}
}
NSLog(#"%#",phoneArray);
BOOL identicalStringFound = NO;
// remove all spaces bracket from contact number which is check
NSMutableString *newCheckingPhoneNumberStr = [[NSMutableString alloc] init];
int j = [checkingPhoneNumber length];
for (int i=0; i<j; i++)
{
if ([checkingPhoneNumber characterAtIndex:i] >=48 && [[profileDetailsDict valueForKey:#"mobile"] characterAtIndex:i] <=59)
{
[newCheckingPhoneNumberStr appendFormat:#"%c",[checkingPhoneNumber characterAtIndex:i]];
}
}
for (NSString *contact in phoneArray)
{
if ([contact isEqual:newCheckingPhoneNumberStr])
{
identicalStringFound = YES;
break;
}
}
if(identicalStringFound)
{
// checkingPhoneNumber is exit
}
else
{
// checkingPhoneNumber is not exit
}
If anybody wants to check name is saved in address book or not, then below function may be useful:
-(BOOL)isNameSaved:(NSString*)strGivenName {
BOOL isSaved = NO;
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for ( int i = 0; i < nPeople; i++ ) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
CFStringRef firstc = (CFStringRef)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
NSString *first = [NSString stringWithFormat:#"%#",firstc];
if ([first isEqualToString:strGivenName]) {
isSaved = YES;
break;
}
}
return isSaved;
}
In my app I have to access the address book, so in iOS>6.0 I have to ask permission to the user.
I do this:
ABAddressBookRef addressBook = ABAddressBookCreate();
if(floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_6_0)
{
//iOS is >= 6.0
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
{
if (granted)
{
[self showContacts:addressBook];
}
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
[self showContacts:addressBook];
}
else
{
//showAccessDeniedAlert();
}
}
else
{
//iOS is < 6.0
[self showContacts:addressBook];
}
In showContacts it's all alright, but: the first time I use the app on a device, it asks me if I want to let it access the AddressBook, i press "OK" and showContactsisn't called! So I have to close the app, restart it, and it works perfectly.
This is my showContacts method:
- (void) showContacts:(ABAddressBookRef)addressBook
{
CFArrayRef allContacts = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfContacts = ABAddressBookGetPersonCount(addressBook);
for (int ii = 0; ii < numberOfContacts; ii++)
{
ABRecordRef contactRef = CFArrayGetValueAtIndex(allContacts, ii);
ABMultiValueRef *phones = ABRecordCopyValue(contactRef, kABPersonPhoneProperty);
for(CFIndex jj = 0; jj < ABMultiValueGetCount(phones); jj++)
{
CEPerson *person = [[CEPerson alloc] init];
NSString *name = (__bridge_transfer NSString *)ABRecordCopyValue(contactRef,kABPersonFirstNameProperty);
NSString *surname = (__bridge_transfer NSString *)ABRecordCopyValue(contactRef, kABPersonLastNameProperty);
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, jj);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
person.name = name;
person.surname = surname;
person.telephone = phoneNumber;
[arrContacts addObject:person];
}
}
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"surname" ascending:YES];
[arrContacts sortUsingDescriptors:[NSArray arrayWithObject:sort]];
[self selectAllContacts];
}
How can I make it work even right after the user presses "OK"?
Thank you all.
I figured it out. I simply added
[tableView reloadData];
at the end of my showContacts method.
I have used following code block in order to retrieve the contacts. The problem is, non of the values are assigned it seems in "contacts" array as expected at the end. I'm very new to threading in iOS. If someone could help me in this, thanks a bunch.
CFErrorRef * error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
{
if (granted)
{
dispatch_async(dispatch_get_main_queue(), ^{
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++){
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSString *name = [NSString stringWithFormat:#"%# %#", firstName, lastName];
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
NSUInteger j = 0;
if (emails) {
for (j = 0; j < ABMultiValueGetCount(emails); j++) {
NSString *email = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(emails, j);
if (j == 0) {
[emailConatcts setValue:email forKey:name];
[contacts addObject:emailConatcts];
}
}
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (phoneNumbers) {
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
CFStringRef label = ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
if (label) {
if (CFEqual(label, kABPersonPhoneMobileLabel)) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
[mobileContacts setValue:phoneNumber forKey:name];
[contacts addObject:emailConatcts];
}
}
}
}
}
});
}
});
NSLog(#"contacts: %#", contacts);
You are asking for the contacts before you have them apparently.
If you move this line
NSLog(#"contacts: %#", contacts);
before this
});
}
});
You should see the data.
The reason is, when you use dispach, and completion blocks, you are telling the system to run that code (usually in a different thread) after a certain operation has finished. So when you were printing the contacts, that block code had not run yet.
So whatever you need to do with the contacts, call it inside that block :)
Does anyone know how to retrieve the Home address from multiaddress in iOS? I have got permission from user and everything else but the problem is, I only want the Home address.
ABAddressBookRef addressBook = ABAddressBookCreate();
__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);
dispatch_release(sema);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *array = [[NSMutableArray alloc] init];
for( int i = 0 ; i < nPeople ; i++ )
{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i );
// First Name
NSString *fName = (__bridge NSString*)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
// Last Name
NSString *lName = (__bridge NSString*)ABRecordCopyValue(ref, kABPersonLastNameProperty);
// Phone
ABMultiValueRef phoneMultiValue = ABRecordCopyValue(ref, kABPersonPhoneProperty);
CFArrayRef allPhones = ABMultiValueCopyArrayOfAllValues(phoneMultiValue);
NSMutableArray *phoneData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allPhones];
// Email
ABMultiValueRef emailMultiValue = ABRecordCopyValue(ref, kABPersonEmailProperty);
CFArrayRef allEmails = ABMultiValueCopyArrayOfAllValues(emailMultiValue);
NSMutableArray *emailData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allEmails];
// Address
ABMultiValueRef addressMultiValue = ABRecordCopyValue(ref, kABPersonAddressProperty);
CFArrayRef allAddresses = ABMultiValueCopyArrayOfAllValues(addressMultiValue);
NSMutableArray* addressData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allAddresses];
for ( int j = 0 ; j < [addressData count]; j++) {
if ([[addressData objectAtIndex:j] count] > 0) {
if ([fName length] > 0 || [lName length] > 0) {
if ([fName length] > 0) {
[dic setObject:fName forKey:#"FirstName"];
}
if ([lName length] > 0) {
[dic setObject:lName forKey:#"LastName"];
}
if ([phoneData count] > 0) {
[dic setObject:phoneData forKey:#"MultiplePhoneNumbers"];
}
if ([emailData count] > 0) {
[dic setObject:emailData forKey:#"MultipleEmails"];
}
[dic setObject:addressData forKey:#"MultipleAddresses"];
}
}
}
NSUInteger keyCount = [[dic allKeys] count];
if (keyCount > 0) {
ABRecordID recId = ABRecordGetRecordID(ref);
[dic setObject:[NSString stringWithFormat:#"%d",recId] forKey:#"ABRecordRef"];
[dic setObject:[NSString stringWithFormat:#"%d",i] forKey:#"ab_id"];
[dic setObject:[NSNumber numberWithBool:FALSE] forKey:#"is_coordinate_fetch"];
[array addObject:dic];
}
I would really appreciate if anyone could take time and solve this for me.
You need to iterate through the kABPersonAddressProperty multivalue property and extract the one matching the kABHomeLabel identifier. Here is how you could do it in iOS 7 (assumes a reference to the address book):
NSArray *people = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(localAddressBook));
// Iterate through each person in the Address Book
for (NSUInteger i = 0; i < people.count; i++)
{
ABRecordRef person = CFArrayGetValueAtIndex((__bridge CFArrayRef)people, i);
// Access the person's addresses (a ABMultiValueRef)
ABMultiValueRef addressesProperty = CFAutorelease(ABRecordCopyValue(person, kABPersonAddressProperty));
if (addressesProperty)
{
// Iterate through the address multivalue
for (CFIndex index = 0; index < ABMultiValueGetCount(addressesProperty); index++)
{
// Get the address label
NSString *addressLabel = (NSString *)CFBridgingRelease(ABMultiValueCopyLabelAtIndex(addressesProperty, index));
// Check for home address label
if ([addressLabel isEqualToString:(NSString *)kABHomeLabel])
{
// Your code here
NSLog(#"%#", addressLabel);
}
}
}
}
There is no single solution to this problem. What I did in my app to do this was as follows:
1) If the person just had one address, use that.
2) If there was more than one address, using cells that had the name and the first address, and a button that said "Select different Address". If the user taps that button, animate up a sheet where the user sees another table of all addresses, and can choose the one they want.