Skip to content

Instantly share code, notes, and snippets.

@HeshamMegid
Last active February 1, 2023 11:28
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save HeshamMegid/4701741 to your computer and use it in GitHub Desktop.
Save HeshamMegid/4701741 to your computer and use it in GitHub Desktop.
Lookup a contact name/photo using phone number in ABAddressBook
#import <Foundation/Foundation.h>
#import "Contact.h"
@interface AddressBookManager : NSObject
+ (NSString *)nameForContactWithPhoneNumber:(NSString *)phoneNumber;
+ (UIImage *)photoForContactWithPhoneNumber:(NSString *)phoneNumber;
@end
#import "AddressBookManager.h"
#import <AddressBook/AddressBook.h>
#import "NSString+UnformattedPhoneNumber.h"
@implementation AddressBookManager
+ (NSArray *)allContactsFromAddressBook {
static NSMutableArray *contacts = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
contacts = [[NSMutableArray alloc] init];
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000
ABAddressBookRef addressBook = ABAddressBookCreate();
#else
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
#endif
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
// Semaphore is used for blocking until response
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
NSArray *allPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
for (id person in allPeople) {
Contact *contact = [[Contact alloc] init];
NSString *firstName = @"";
NSString *lastName = @"";
// Get the name of the contact
firstName = (__bridge_transfer NSString*)ABRecordCopyValue((__bridge ABRecordRef)(person), kABPersonFirstNameProperty);
lastName = (__bridge_transfer NSString*)ABRecordCopyValue((__bridge ABRecordRef)(person), kABPersonLastNameProperty);
[contact setName:[NSString stringWithFormat:@"%@ %@", firstName, lastName]];
// Get the photo of the contact
CFDataRef imageData = ABPersonCopyImageData((__bridge ABRecordRef)(person));
UIImage *image = [UIImage imageWithData:(__bridge NSData *)imageData];
[contact setPhoto:image];
// Get all phone numbers of the contact
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)(person), kABPersonPhoneProperty);
// If the contact has multiple phone numbers, iterate on each of them
NSInteger phoneNumberCount = ABMultiValueGetCount(phoneNumbers);
for (int i = 0; i < phoneNumberCount; i++) {
NSString *phoneNumberFromAB = [(__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, i) unformattedPhoneNumber];
[tempArray addObject:phoneNumberFromAB];
}
CFRelease(phoneNumbers);
[contact setNumbers:tempArray];
[contacts addObject:contact];
}
}
CFRelease(addressBook);
});
return contacts;
}
+ (Contact *)findContactWithPhoneNumber:(NSString *)phoneNumber {
NSArray *contacts = [AddressBookManager allContactsFromAddressBook];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"numbers contains %@", phoneNumber];
NSArray *filteredArray = [contacts filteredArrayUsingPredicate:predicate];
Contact *matchedContact = [filteredArray lastObject];
return matchedContact;
}
+ (NSString *)nameForContactWithPhoneNumber:(NSString *)phoneNumber {
return [[AddressBookManager findContactWithPhoneNumber:phoneNumber] name];
}
+ (UIImage *)photoForContactWithPhoneNumber:(NSString *)phoneNumber {
return [[AddressBookManager findContactWithPhoneNumber:phoneNumber] photo];
}
@end
#import <Foundation/Foundation.h>
@interface Contact : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSArray *numbers;
@property (nonatomic, strong) UIImage *photo;
@end
#import "Contact.h"
@implementation Contact
@end
#import <Foundation/Foundation.h>
@interface NSString (UnformattedPhoneNumber)
- (NSString *)unformattedPhoneNumber;
@end
#import "NSString+UnformattedPhoneNumber.h"
@implementation NSString (UnformattedPhoneNumber)
- (NSString *)unformattedPhoneNumber {
NSCharacterSet *toExclude = [NSCharacterSet characterSetWithCharactersInString:@"/.()- "];
return [[self componentsSeparatedByCharactersInSet:toExclude] componentsJoinedByString: @""];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment