I am trying to get selected mobile phone number with
ABMultiValueRef phones = ABRecordCopyValue(person, property);
CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(phones, identifier);
I have a contact with several mobile phones (all labeled 'mobile'). When I select the first one, phoneNumber gives me the first one, but if I select any consecutive one, phoneNumber gives me the previous number:
Contact:
Jay Jaymes
mobile +1111111111
mobile +2222222222
mobile +3333333333
Tap first one, phoneNumber = +1111111111
Tap second one, phoneNumber = +1111111111
Tap third one, phoneNumber = +2222222222
This is code I use. And It will give correct phone number only
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
if (property == kABPersonPhoneProperty) {
ABMultiValueRef phoneProperty = ABRecordCopyValue(person,property);
CFIndex peopleIndex = ABMultiValueGetIndexForIdentifier(property, identifier);
NSString *phone = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(phoneProperty, peopleIndex);
[self dismissModalViewControllerAnimated:YES];
}
return NO;
}
You can easily iterate like that. Try NSLoging that code to make sure it works.
I think you have some bugs in your "choosing" logic.
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (CFIndex i=0; i < ABMultiValueGetCount(phones); i++)
{
NSString* phoneLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
NSString* phoneNumber = ABMultiValueCopyValueAtIndex(phones, i);
//release variables since you were using COPY !!!
CFRelease(phoneNumber);
CFRelease(phoneLabel);
}
CFRelease(phones);
Ended up implementing it this way:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
if (property == kABPersonPhoneProperty)
{
ABMultiValueRef phones = ABRecordCopyValue(person, property);
CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(phones, identifier);
NSLog(#"%#", phoneNumber);
NSMutableString *tmp = [NSMutableString stringWithFormat:#"%#", (__bridge_transfer NSString *)phoneNumber];
NSString *strippedPhoneNumber = [tmp stringByReplacingOccurrencesOfString:#" " withString:#""];
NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:#"()-"];
strippedPhoneNumber = [[strippedPhoneNumber componentsSeparatedByCharactersInSet: doNotWant] componentsJoinedByString: #""];
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
[peoplePicker dismissViewControllerAnimated:YES completion:nil];
return NO;
}
You should not be using the identifier as the index within ABMultiValueCopyValueAtIndex. You should call ABMultiValueGetIndexForIdentifier to convert the ABMultiValueIdentifier identifier into a CFIndex index:
ABMultiValueRef phones = ABRecordCopyValue(person, property);
CFIndex index = ABMultiValueGetIndexForIdentifier(phones, identifier);
NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, index));
CFRelease(phones);
Generally, the ABMultiValueIdentifier values match the CFIndex values retrieved by ABMultiValueGetIndexForIdentifier, but if a contact was edited (specifically if one of the earlier phone numbers was deleted), using the ABMultiValueIdentifier in ABMultiValueCopyValueAtIndex will return the wrong record.
Related
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.
[background: iOS 7, Xcode 5, both up to date as of Feb 2014. Test data is address book entries with multiple phone numbers and multiple addresses in addition to basic contact info, on an iPhone 5 (real device, not simulator)]
My goal is to use the AddressBookUI methods to allow a user to specify a contact, then use the various fields (addresses, phone numbers, etc) to populate a GUI in my code. The ABPeoplePickerNavigationController is the standard mechanism to allow the user to pick a contact by name. Doing so results in this delegate method being called:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
However if I examine the person record at this point, none of the multi-value fields have any data. So I extracted the RecordID, retrieved that, and the resulting ABRecordRef also has no multi-value fields filled in.
If I return YES from the delegate method, another UI is shown to the user with contact details displayed. Touching any field results in this delegate method call
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
and that ABRecordRef has all the multi value fields filled in.
I can't find any information about the records being lazily loaded, or there being either a required delay, or permissions issue that would prevent the fields from being filled in. And the code I am using to examine the records is a method, so the exact same code which finds the values in the second instance fails to find it in the first.
Any suggestions about what may be going on, or how I can retrieve the full records without displaying the second UI to the user?
I am using Apple's QuickContacts sample code. Here are the additions and changes I have made.
+(NSMutableDictionary *)convertABRecordRef:(ABRecordRef)person
{
// Initialize a mutable dictionary and give it initial values.
NSMutableDictionary *contactInfoDict = [[NSMutableDictionary alloc] initWithCapacity:12];
// Use a general Core Foundation object.
CFTypeRef generalCFObject = ABRecordCopyValue(person, kABPersonFirstNameProperty);
ABRecordID foundId = ABRecordGetRecordID(person);
NSNumber *personIDNum = [NSNumber numberWithInteger:foundId];
[contactInfoDict setObject:personIDNum forKey:#"recordID"];
// Get the first name.
if (generalCFObject)
{
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"firstName"];
CFRelease(generalCFObject);
}
// Get the last name.
generalCFObject = ABRecordCopyValue(person, kABPersonLastNameProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"lastName"];
CFRelease(generalCFObject);
}
generalCFObject = ABRecordCopyValue(person, kABPersonOrganizationProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"companyName"];
CFRelease(generalCFObject);
}
//ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
//NSArray *numbers = (NSArray *)ABMultiValueCopyArrayOfAllValues(phones);
// Get the phone numbers as a multi-value property.
ABMultiValueRef phonesRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phoneCount = ABMultiValueGetCount(phonesRef);
for (CFIndex i=0; i<ABMultiValueGetCount(phonesRef); i++) {
CFStringRef currentPhoneLabel = ABMultiValueCopyLabelAtIndex(phonesRef, i);
CFStringRef currentPhoneValue = ABMultiValueCopyValueAtIndex(phonesRef, i);
if (CFStringCompare(currentPhoneLabel, kABPersonPhoneMobileLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentPhoneValue forKey:#"mobileNumber"];
}
if (CFStringCompare(currentPhoneLabel, kABHomeLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentPhoneValue forKey:#"homeNumber"];
}
if (CFStringCompare(currentPhoneLabel, kABWorkLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentPhoneValue forKey:#"workNumber"];
}
CFRelease(currentPhoneLabel);
CFRelease(currentPhoneValue);
}
CFRelease(phonesRef);
// Get the e-mail addresses as a multi-value property.
ABMultiValueRef emailsRef = ABRecordCopyValue(person, kABPersonEmailProperty);
for (int i=0; i<ABMultiValueGetCount(emailsRef); i++)
{
CFStringRef currentEmailLabel = ABMultiValueCopyLabelAtIndex(emailsRef, i);
CFStringRef currentEmailValue = ABMultiValueCopyValueAtIndex(emailsRef, i);
if (CFStringCompare(currentEmailLabel, kABHomeLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentEmailValue forKey:#"homeEmail"];
}
if (CFStringCompare(currentEmailLabel, kABWorkLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentEmailValue forKey:#"workEmail"];
}
CFRelease(currentEmailLabel);
CFRelease(currentEmailValue);
}
CFRelease(emailsRef);
// Get the first street address among all addresses of the selected contact.
ABMultiValueRef addressRef = ABRecordCopyValue(person, kABPersonAddressProperty);
if (ABMultiValueGetCount(addressRef) > 0)
{
CFIndex numberOfAddresses = ABMultiValueGetCount(addressRef);
for (CFIndex i=0; i<numberOfAddresses; i++)
{
CFStringRef label = ABMultiValueCopyLabelAtIndex(addressRef, i);
if (label)
{
if (CFEqual(label, kABHomeLabel))
{
NSDictionary *addressDict = (__bridge NSDictionary *)ABMultiValueCopyValueAtIndex(addressRef, 0);
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressStreetKey] forKey:#"homeAddress"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressZIPKey] forKey:#"homeZipCode"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressCityKey] forKey:#"homeCity"];
}
else if (CFEqual(label, kABWorkLabel))
{
NSDictionary *addressDict = (__bridge NSDictionary *)ABMultiValueCopyValueAtIndex(addressRef, 0);
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressStreetKey] forKey:#"workAddress"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressZIPKey] forKey:#"workZipCode"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressCityKey] forKey:#"workCity"];
}
CFRelease(label);
}
}
}
CFRelease(addressRef);
// If the contact has an image then get it too.
if (ABPersonHasImageData(person)) {
NSData *contactImageData = (__bridge NSData *)ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail);
[contactInfoDict setObject:contactImageData forKey:#"image"];
}
return contactInfoDict;
}
// Displays the information of a selected person
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
// only returns a few fields, and none of the multi value ones :-(
NSMutableDictionary *results = [QuickContactsViewController convertABRecordRef:person];
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABRecordID foundId = ABRecordGetRecordID(person);
ABRecordRef fullPerson = ABAddressBookGetPersonWithRecordID(addressBook, foundId);
// also only returns a few fields!?
NSMutableDictionary *selectedFromID = [QuickContactsViewController convertABRecordRef:fullPerson];
return YES;
}
// Does not allow users to perform default actions such as dialing a phone number, when they select a person property.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
// returns all simple and multi-value fields!?
NSMutableDictionary *results = [QuickContactsViewController convertABRecordRef:person];
return NO;
}
EDIT: Adding my solution (thanks Thorsten!).
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
NSArray *allPersonRecords = (NSArray *)CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(person));
NSLog(#"Count Linked People: %i", allPersonRecords.count);
NSMutableDictionary *results = [[NSMutableDictionary alloc]initWithCapacity:12];
for (int x=0; x<[allPersonRecords count]; x++)
{
ABRecordRef user = CFBridgingRetain([allPersonRecords objectAtIndex:x]);
NSMutableDictionary *userFromArray = [QuickContactsViewController convertABRecordRef:user];
[results addEntriesFromDictionary:userFromArray]; // mush them together
CFRelease(user);
}
NSLog(#"finished! Total number of contact fields found:%d", [results count]);
// do something with the data here...
return NO;
}
One person can consist of multiple people. Iterate through all people to get your data:
NSArray *people = (NSArray *)CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(person));
...
ABRecordRef user = CFBridgingRetain([people objectAtIndex:i]);
...
valuesRef = ABRecordCopyValue(user, kABPersonPhoneProperty);
valuesCount = 0;
if (valuesRef != nil) valuesCount = ABMultiValueGetCount(valuesRef);
...
HTH
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);
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;
Overview: I am trying to get the phone number and full name when people use the peoplePicker and clicks on the name. Then, I'd like to display the full name on a textfield and save the phone number as a string. Using the ph num and name, I intend to use that as a unique identification. I don't want to use the unique id of ABRecord because sometimes i have duplicates on my contacts especially when I sync it with google, etc...
If I understand correctly, I need to use this delegate method
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
Using the above, I can get the full name to display on the text field as scuh
textField.text = ABRecordCopyCompositeName(person);
But, I don't know how to get the ph number. For me to get the ph number, I have to use the other delegate method:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
ABMultiValueRef phoneProperty = ABRecordCopyValue(person,property);
NSString *phone = (NSString *)ABMultiValueCopyValueAtIndex(phoneProperty,identifier);
However, I don't like this because then when the user clicks on the name on the address book, it shows the detail with the ph number, email, etc and the user has to click on the ph number. What I want is from the first screen, the user clicks on the name and the name gets displayed as a textField and the ph number is saved as a string somewhere.
I use a method to save all persons with emails in a array and then display the array in a table view:
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *mArr = [[NSMutableArray alloc]init];
for( int i = 0 ; i < nPeople ; i++ )
{
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
NSString *preName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *postName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
ABMultiValueRef emails = (ABMultiValueRef) ABRecordCopyValue(person, kABPersonEmailProperty);
int ecount = ABMultiValueGetCount(emails);
for (int i = 0; i < ecount; i++) {
NSMutableDictionary *dd = [[NSMutableDictionary alloc]init];
[dd setValue:[NSString stringWithFormat:#"%# %#", preName, postName] forKey:#"name"];
NSString *emailID = (NSString *)ABMultiValueCopyValueAtIndex(emails, i);
[dd setValue:emailID forKey:#"mail"];
//NSLog(#"inside loop %# %# %#", preName, postName, emailID);
[emailID release];
[mArr addObject:dd];
[dd release];
}
}
emailArray = [[NSArray alloc]initWithArray:mArr];
[mArr release];
If you want to get just the first email and phone number use this code. This is for iOS 5.0 with Xcode 4.2
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
//NSLog(#"Went here 1 ...");
NSString *nameStr = (__bridge NSString *)ABRecordCopyCompositeName(person);
ABMultiValueRef emails = (ABMultiValueRef) ABRecordCopyValue(person, kABPersonEmailProperty);
ABMultiValueRef phones = (ABMultiValueRef) ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString *emailStr = (__bridge NSString *)ABMultiValueCopyValueAtIndex(emails, 0);
NSString *phoneStr = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phones, 0);
//strip number from brakets
NSMutableString *tmpStr1 = [NSMutableString stringWithFormat:#"%#", phoneStr];
NSString *strippedStr1 = [tmpStr1 stringByReplacingOccurrencesOfString:#" " withString:#""];
NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:#"()-"];
strippedStr1 = [[strippedStr1 componentsSeparatedByCharactersInSet: doNotWant] componentsJoinedByString: #""];
NSLog(#"nameStr: %# ... emailStr: %# ... phoneStr: %# ...", nameStr, emailStr,strippedStr1);
//dismiss
[self dismissModalViewControllerAnimated:YES];
return NO;
}