An Easy Way To Use Contact Picker
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]