Today I had to load a Contact browser in my iPhone application I have to say I was surprised to see how easy it was!
The first thing that I thought about was to… google for it. Sure, I didn't know this side of the API and I imagined I would have to query some address book database and then build a table view using my query results as datasource. And guess what, this can actually be done very easily.
Luckily I looked deeper in the SDK API and found that there is a Navigation Controller already available that does everything I need.
Here are the steps I had to follow in order to implement this functionality.
1. Imports
Add the AddressBook and AddressBookUI frameworks to my project (control click the Target and then Get Info and Add Framework)
2. Set up the controller
Create an instance of ABPeoplePickerNavigationController on the control that you want to trigger the contact selection.
3. Set up a delegate
The controller will make a series of callbacks which is why you need to implement a protocol that is the actual delegate for the above controller. The delegate is ABPeoplePickerNavigationControllerDelegate and the callback methods are below:
– (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker;
Gets called when the user taps the Cancel navigation button. Here you should dismiss the person picker navigation controller. See point 4 below.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person;
This is the place where you get access to the actual section therefore you have to make sure you use the person reference to extract the data you need. See point 5 below. If you want the user to get detailed information about the selected user return YES, if you're only after the name and want to limit navigation just return NO.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier;
This is where you take action if the user taps various properties such as phone number, email, etc If you are simply after the person's name like I was simply return NO.
4. Loading the controller and dismissing it
You load the ABPeoplePickerNavigationController using your current navigation controller's presentModalViewController method. You implement this wherever you handle the tap / action on the triggering control.
When the user taps cancel you dismiss the people picker controller via the dismissModalViewControllerAnimated method belonging to your controller. You implement this in the peoplePickerNavigationControllerDidCancel method above.
5. Extracting the relevant information
The ABRecordRef pointer gives you access to the contacts details. Here is how you'd extract the contact's first name:
CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
Notice the kABPersonFirstNameProperty constant. There are many more like this one that enable you to get the data you need. Here is the complete list:
kABPersonFirstNameProperty
kABPersonLastNameProperty
kABPersonMiddleNameProperty
kABPersonPrefixProperty
kABPersonSuffixProperty
kABPersonNicknameProperty
kABPersonFirstNamePhoneticProperty
kABPersonLastNamePhoneticProperty
kABPersonMiddleNamePhoneticProperty
kABPersonOrganizationProperty
kABPersonJobTitleProperty
kABPersonDepartmentProperty
kABPersonEmailProperty
kABPersonBirthdayProperty
kABPersonNoteProperty
kABPersonCreationDateProperty
kABPersonModificationDateProperty
Don't let the CFString data type scare you. You can simply cast to a (NSString *) and use it… This is just one of the interchangeable data types, but that will be another post.
Cheers…