An Easy Way To Use Contact Picker

Umar Ashfaq
Eastros
Published in
2 min readMay 20, 2014

API for selecting a contact in iOS seems unnecessarily difficult, it becomes a nightmare when you have to use it again and again at different places in your project. I think the idea of delegates is over-used in iOS, and they could have made things much simpler by relying on blocks instead.

So here again, instead of creating delegates again and again, I created a simple wrapper class that encapsulates the ugliness of the API and offers a clean way to the end developer. Here is how I use it in a view controller:

[sourcecode language=”objc”]
ETPeoplePicker *picker = [[ETPeoplePicker alloc] initWithViewController:self andSuccessBlock:^(NSString *name, NSString *number) {
NSLog(@”You selected %@”, number);
} andFailureBlock:^ {

}];
[picker show];
[/sourcecode]

That’s it. Here is the code for ETPeoplePicker:

[sourcecode language=”objc”]
//
// ETPeoplePicker.h
//
// Created by Umar Ashfaq on 5/16/14.
//

#import <Foundation/Foundation.h>
#import <AddressBookUI/AddressBookUI.h>

typedef void(^ETPeoplePickerSuccessBlock)(NSString *name, NSString *number);
typedef void(^ETPeoplePickerFailureBlock)();

@interface ETPeoplePicker : UIView<ABPeoplePickerNavigationControllerDelegate>

-(id)initWithViewController:(UIViewController *)viewController andSuccessBlock:(ETPeoplePickerSuccessBlock)success andFailureBlock:(ETPeoplePickerFailureBlock)failure;

-(void) show;

@end

//
// ETPeoplePicker.m
//
// Created by Umar Ashfaq on 5/16/14.
//

#import “ETPeoplePicker.h”
#import “ETUtils.h”
#import <AddressBookUI/AddressBookUI.h>
#import “ETSentItemPreviewViewController.h”

@interface ETPeoplePicker() <ABPeoplePickerNavigationControllerDelegate>

@property(nonatomic, strong) ETPeoplePickerSuccessBlock success;
@property(nonatomic, strong) ETPeoplePickerFailureBlock failure;
@property(nonatomic, strong) UIViewController* viewController;

@end

@implementation ETPeoplePicker

-(id)initWithViewController:(UIViewController *)viewController andSuccessBlock:(ETPeoplePickerSuccessBlock)success andFailureBlock:(ETPeoplePickerFailureBlock)failure
{
self = [super init];

if ( self )
{
_viewController = viewController;
_success = success;
_failure = failure;
}

return self;
}

-(void) show
{
ABPeoplePickerNavigationController *abPicker = [[ABPeoplePickerNavigationController alloc] init];
abPicker.peoplePickerDelegate = self;
abPicker.delegate = (ETSentItemPreviewViewController *) self.viewController;
[self.viewController presentViewController:abPicker animated:NO completion:nil];
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
[peoplePicker dismissViewControllerAnimated:NO completion:nil];

// recipient = person;
NSString *recipientName = (__bridge NSString *)(ABRecordCopyCompositeName(person));
NSString *recipientPhone;

// recipientPhone = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonPhoneProperty));
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if ( ABMultiValueGetCount(phoneNumbers) > 0 )
{
recipientPhone = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneNumbers, 0));
recipientPhone = [ETUtils normalizePhoneNumber:recipientPhone];
}
CFRelease(phoneNumbers);

NSLog(@”Selected number: %@”, recipientPhone);
self.success(recipientName, recipientPhone);

return NO;
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
[peoplePicker dismissViewControllerAnimated:YES completion:nil];
return NO;
}

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[peoplePicker dismissViewControllerAnimated:YES completion:nil];
}

@end

[/sourcecode]

--

--