fetching only Character of email from address book - ios

i have used following code for getting for getting information from address book
ABRecordRef ref = CFArrayGetValueAtIndex(allPeopleName, i );
NSString* personName = (__bridge_transfer NSString*) ABRecordCopyValue(ref, kABPersonFirstNameProperty);
NSDate* Date = (__bridge_transfer NSDate*) ABRecordCopyValue(ref, kABPersonBirthdayProperty);
**NSString* personEmail = (__bridge_transfer NSString*) ABRecordCopyValue(ref, kABPersonEmailProperty);**
NSString *birthdayDate = [dateFormat stringFromDate:Date];
**NSLog(#"personEmail%#",personEmail);**
// this is what personaEmail prints
personEmailABMultiValueRef 0x8a64740 with 2 value(s)
0: $!!$ (0x8a2bea0) - miou#yahoo.in (0x8a41df0)
1: $!!$ (0x8a423c0) - minadi#yahoo.com (0x8a64720)
ABMultiValueRef phones = (ABMultiValueRef)ABRecordCopyValue(ref, kABPersonPhoneProperty);
NSString* mobile=#"";
NSString* mobileLabel;
for (int i=0; i < ABMultiValueGetCount(phones); i++) {
//NSString *phone = (NSString *)ABMultiValueCopyValueAtIndex(phones, i);
//NSLog(#"%#", phone);
mobileLabel = (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 release];
mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(#"%#", mobile);
NSCharacterSet* charactersToRemove = [[NSCharacterSet decimalDigitCharacterSet] invertedSet] ;
mobile = [[mobile componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:#""] ;
}
now my question are
how can i get only email from that all other stuff
i always want only one email id not two how can i get only home email id? doesnt matter how many email ids are there in address book

personEmail (or, more correctly, the return value of ABRecordCopyValue(ref, kABPersonEmailProperty)) isn't a NSString. Look at the log message - it's a ABMultiValueRef.
You will want to use the methods described in this documentation to access individual components.

This will print all the email id. You can take the necessary one.
NSString *email;
CFStringRef value, label;
ABMutableMultiValueRef multi = ABRecordCopyValue(person, kABPersonEmailProperty);
CFIndex count = ABMultiValueGetCount(multi);
if (count == 1)
{
value = ABMultiValueCopyValueAtIndex(multi, 0);
email = (__bridge NSString*) value;
NSLog(#"EmailID %#",email);
CFRelease(value);
}
else
{
for (CFIndex i = 0; i < count; i++)
{
label = ABMultiValueCopyLabelAtIndex(multi, i);
value = ABMultiValueCopyValueAtIndex(multi, i);
// check for Work e-mail label
if (CFStringCompare(label, kABWorkLabel, 0) == 0)
{
email = (__bridge NSString*) value;
NSLog(#"EmailID %#",email);
}
// check for Home e-mail label
else if(CFStringCompare(label, kABHomeLabel, 0) == 0)
{
email = (__bridge NSString*) value;
NSLog(#"EmailID %#",email);
}
CFRelease(label);
CFRelease(value);
}
}
CFRelease(multi);

Related

how to save one name string and two different length array of email and phone no

As i guess this is a very simple and basic question.
i am using #import <AddressBook/AddressBook.h> to get the contact info of device and i had successfully implemented the same.
Everythings work fine when i got one phone no and one email from each contact. But when i got multiple phone no's and multiple email then getting crash on my app. I guess i am not using the proper saving method.
So i really want to know how to save one name string and one array of email(different length) and phone no(different length) as group for a contact and same for all other. so that it would not be difficult to reproduce the result later on the detail screen
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));
[values1 addObject:[NSString stringWithFormat:#"%# %#",firstName,lastName]]; //values1 array to save name of contact
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++) {
NSString* email = (__bridge NSString*)ABMultiValueCopyValueAtIndex(emails, j);
NSLog(#"Email:%#", email);
[values2 addObject:[NSString stringWithFormat:#"%#",email]];
} //values2 array to save email associated to that contact
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSLog(#"phone:%#", phoneNumber);
[values3 addObject:[NSString stringWithFormat:#"%#",phoneNumber]];
}//values3 array to save different phone no's associated to that contacts
NSDictionary *dict = [[NSDictionary alloc]init];
}
AS now i have three array with details contain details of one contact. Now how can merge these three array values to one so that it would be easy to save and fetch data for multiples or hundreds of contacts
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");
}
You can see multiple contact and email in log if contact have.

Fetch mobile number programmatically

I am developing an app in iOS. I can retrieve the first and last name of person but what i want is how can I retrieve the mobile number information. I already have this code to fetch first and last name.
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (addressBook != nil) {
NSLog(#"Succesful.");
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSUInteger i = 0; for (i = 0; i < [allContacts count]; i++)
{
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson,kABPersonFirstNameProperty);
lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
} else {
NSLog(#"Error Reading Address Book");
}
You can get all phone entries using the code below.
I also specified few types of phone types to give you an idea how to deal with that.
ABMultiValueRef phoneNumbers = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
for (CFIndex i=0; i < ABMultiValueGetCount(phoneNumbers); i++)
{
NSString* phoneLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
NSString* phoneNumber = ABMultiValueCopyValueAtIndex(phoneNumbers, i);
if([phoneLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
{
}
else if([phoneLabel isEqualToString:(NSString *)kABPersonPhoneIPhoneLabel])
{
}
CFRelease(phoneNumber);
CFRelease(phoneLabel);
}
CFRelease(phoneNumbers);
You can fetch phone numbers using below code
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
Try this
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < nPeople; i++)
{
// Getting the person record ...
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (CFIndex i=0; i < ABMultiValueGetCount(phones); i++)
{
NSString* phoneLabel = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
NSString* phoneNumber = (__bridge_transfer NSString*) ABMultiValueCopyValueAtIndex(phones, i);
}
CFRelease(phones);
}
CFRelease(allPeople);
CFRelease(addressBook);

How to Synchronize iPhone numbers fetched from contacts with the contact names?

I am creating one app in which I have to fetch the contacts of the iPhone and call through that application using this.
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 = (NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
[TempArray addObject:[NSString stringWithFormat:#"%#",firstName]];
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++)
{
NSString *phoneNumber = (NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
[PhoneNumbers addObject:phoneNumber];
}
}
I am getting both the numbers and names in different array.But there are some Contact Names with more than one number so the components in Number Array comes more.
Is there anything that can synchronize both number and contacts together?
Is there anything with which we can scan mobile numbers and land line numbers in that list?
Also when fetching the contacts can we fetch the complete name of a friend at once,without using kABPersonFirstNameProperty or kABPersonLastNameProperty and appending?
Any Suggestions?
I had to work around some time to get to this done.I had to use ABMultiValueCopyLabelAtIndex to get the kind of contact and comparing to both kABPersonPhoneMobileLabel and kABPersonPhoneIPhoneLabel and fetching the contacts details in the dictionary form.In this form the numbers are synchronized with names.
contactList=[[NSMutableArray alloc] init];
ABAddressBookRef m_addressbook = ABAddressBookCreate();
if (!m_addressbook) {
NSLog(#"opening address book");
}
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(m_addressbook);
CFIndex nPeople = ABAddressBookGetPersonCount(m_addressbook);
for (int i=0;i < nPeople;i++) {
NSMutableDictionary *dOfPerson=[NSMutableDictionary dictionary];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
//For username and surname
ABMultiValueRef phones =(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:(NSString *)ABMultiValueCopyValueAtIndex(eMail, 0) forKey:#"email"];
}
//For Phone number
NSString* mobileLabel;
for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) {
mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
{
[dOfPerson setObject:(NSString*)ABMultiValueCopyValueAtIndex(phones, i) forKey:#"Phone"];
}
else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel])
{
[dOfPerson setObject:(NSString*)ABMultiValueCopyValueAtIndex(phones, i) forKey:#"Phone"];
break ;
}
[contactList addObject:dOfPerson];
}
NSLog(#"array is %#",contactList);
}

ABAddressBook search logic, potential leaks

I have this code for searching in the AddressBook and xcode suggests me that i have potential leaks in firstName, lastName, and another object that is unknown even to xcode. I tried to release the first 2 of them and the warning disappears but my app is crashing. Also i have a random crash on this line, i got it only once but appears in crashlytics for other people. Do you see anything wrong with my code? Thanks.
ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonPhoneProperty);
The code. It's purpose is to group all the contacts by the first letter of the name and to duplicate the contacts in case they have multiple numbers.
- (void)filterByKeyword:(NSString*)keyword completionBlock:(AddressBookSearchCompletionBlock)completionBlock {
dispatch_async(abQueue, ^{
[self.filteredContacts removeAllObjects];
// Iterate over original contacts
for (id evaluatedObject in self.allContacts) {
CFStringRef n = ABRecordCopyCompositeName((__bridge ABRecordRef)evaluatedObject);
NSString *name = (__bridge_transfer NSString*)n;
if (name == nil) {
RCLog(#"name is nil. skip this contact");
continue;
}
if (keyword == nil || [[name lowercaseString] rangeOfString:keyword].location != NSNotFound)
{
NSString *key = [[name substringToIndex:1] uppercaseString];
if (key == nil || [key isEqualToString:#"_"]) {
key = #"#";
}
NSMutableArray *arr = [self.filteredContacts objectForKey:key];
if (arr == nil) {
arr = [[NSMutableArray alloc] init];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonPhoneProperty);
signed long num = ABMultiValueGetCount(phoneNumbers);
if (num == 0) {
[arr addObject:evaluatedObject];
}
else {
for (CFIndex i = 0; i < num; i++) {
if (i > 0) {
// Create a separate contact with the alternative phone numbers of a contact
NSString* phoneNumber = (__bridge_transfer NSString*) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSString* phoneNumericNumber = [phoneNumber stringByTrimmingCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
if (phoneNumber != nil && phoneNumber.length > 0 && phoneNumericNumber.length > 0) {
ABRecordRef persona = ABPersonCreate();
CFStringRef firstName = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue((__bridge ABRecordRef)evaluatedObject, kABPersonLastNameProperty);
ABRecordSetValue (persona, kABPersonFirstNameProperty, firstName, nil);
ABRecordSetValue (persona, kABPersonLastNameProperty, lastName, nil);
ABMutableMultiValueRef multiPhone = ABMultiValueCreateMutable(kABMultiStringPropertyType);
bool didAddPhone = ABMultiValueAddValueAndLabel(multiPhone, (__bridge CFTypeRef)(phoneNumber), kABPersonPhoneMobileLabel, NULL);
if (didAddPhone){
ABRecordSetValue(persona, kABPersonPhoneProperty, multiPhone, nil);
}
if (ABPersonHasImageData((__bridge ABRecordRef)evaluatedObject)) {
ABPersonSetImageData(persona, ABPersonCopyImageDataWithFormat((__bridge ABRecordRef)evaluatedObject, kABPersonImageFormatThumbnail), nil);
}
[arr addObject:(__bridge id)persona];
CFRelease(multiPhone);
CFRelease(persona);
}
}
else {
[arr addObject:evaluatedObject];
}
}
}
CFRelease(phoneNumbers);
[self.filteredContacts setObject:arr forKey:key];
RCLog(#"%i contacts for key %#", arr.count, key);
}
}
self.filteredKeys = [[self.filteredContacts allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock();
});
});
}

kABPersonEmailProperty returns weird stuff

I am tring to get email address of ABRecordRef like this:
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
NSString *email = [(NSString*) ABRecordCopyValue( ref, kABPersonEmailProperty ) autorelease];
NSLog(#"%#", email);
It returning this:
_$!<Home>!$_ (0x6840af0) - test#test.com (0x6840cc0)
What's this stuff around the email? and how can I get rid of it?Thanks.
kABPersonEmailProperty is of type kABMultiStringPropertyType. There is no single email address property, a person might have an email address for work, one for home, etc.
You can get an array of all email addresses by using ABMultiValueCopyArrayOfAllValues:
ABMultiValueRef emailMultiValue = ABRecordCopyValue(ref, kABPersonEmailProperty);
NSArray *emailAddresses = [(NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue) autorelease];
CFRelease(emailMultiValue);
To get the labels of the email addresses, use ABMultiValueCopyLabelAtIndex. "_$!<Home>!$" is a special constant that's defined as kABHomeLabel, there's also kABWorkLabel.
Basically more details for #omz answer. Here is the code I used that extracts home email and the name of the person:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(emails); i++) {
NSString *label = (__bridge NSString *) ABMultiValueCopyLabelAtIndex(emails, i);
if ([label isEqualToString:(NSString *)kABHomeLabel]) {
NSString *email = (__bridge NSString *) ABMultiValueCopyValueAtIndex(emails, i);
_emailTextField.text = email;
}
}
CFRelease(emails);
NSString *first = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *last = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
if (first && first.length > 0 && last && last.length > 0) {
_nicknameTextField.text = [NSString stringWithFormat:#"%# %#", first, last];
} else if (first && first.length > 0) {
_nicknameTextField.text = first;
} else {
_nicknameTextField.text = last;
}
[self dismissModalViewControllerAnimated:YES];
return NO;
}
Try out this......
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
// Display only a person's phone, email, and birthdate
NSArray *displayedItems = [NSArray arrayWithObjects:
[NSNumber numberWithInt:kABPersonPhoneProperty],
[NSNumber numberWithInt:kABPersonEmailProperty],
[NSNumber numberWithInt:kABPersonBirthdayProperty], nil];
picker.displayedProperties = displayedItems;

Resources