Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search ABAddressbook iOS SDK

I want to search the iPhone address book for a specific phone number, and then retrieve the contact name. I am currently looping through all contacts and extracting the multivalue properties and comparing against the value. This is taking way too much time. I have read the Apple addressbook guide, and they say:

"accomplish other kinds of searches, use the function ABAddressBookCopyArrayOfAllPeople and then filter the results using the NSArray method filteredArrayUsingPredicate:."

Can anyone give me an example on how to exactly do that?

Thanks.

like image 766
Rabih Avatar asked Mar 01 '11 10:03

Rabih


2 Answers

If you want to do a search in the contacts with phone number, then I will tell you one suggestion.

1.Get all contacts

NSArray *thePeoples = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);

2.Create another array(records) from the contacts array(thePeoples),

records:[ record1, record2, ....recordN ]

record: {name:"myContactName", phoneNumber:"1234567890"}

3.Search the mutableArray(records) with predicate.

NSPredicate * myPredicate = [NSPredicate predicateWithFormat:@"record.phoneNumber contains %@",string];

NSArray * filteredArray = [records filteredArrayUsingPredicate:myPredicate];

This is just a simple example to your solution, and remember phoneNumber is a multiValue field. So we will include an array as phone number in the model class variable.

like image 71
Jay Avatar answered Sep 20 '22 12:09

Jay


The following method will return an array that contains all of the contacts that have the given phone number. This method took 0.02 seconds to search 250 contacts on my iPhone 5 running iOS7.

#import <AddressBook/AddressBook.h>


-(NSArray *)contactsContainingPhoneNumber:(NSString *)phoneNumber {
    /*

     Returns an array of contacts that contain the phone number

     */

    // Remove non numeric characters from the phone number
    phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:@""];

    // Create a new address book object with data from the Address Book database
    CFErrorRef error = nil;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    if (!addressBook) {
        return [NSArray array];
    } else if (error) {
        CFRelease(addressBook);
        return [NSArray array];
    }

    // Requests access to address book data from the user
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {});

    // Build a predicate that searches for contacts that contain the phone number
    NSPredicate *predicate = [NSPredicate predicateWithBlock: ^(id record, NSDictionary *bindings) {
        ABMultiValueRef phoneNumbers = ABRecordCopyValue( (__bridge ABRecordRef)record, kABPersonPhoneProperty);
        BOOL result = NO;
        for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
            NSString *contactPhoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
            contactPhoneNumber = [[contactPhoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:@""];
            if ([contactPhoneNumber rangeOfString:phoneNumber].location != NSNotFound) {
                result = YES;
                break;
            }
        }
        CFRelease(phoneNumbers);
        return result;
    }];

    // Search the users contacts for contacts that contain the phone number
    NSArray *allPeople = (NSArray *)CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
    NSArray *filteredContacts = [allPeople filteredArrayUsingPredicate:predicate];
    CFRelease(addressBook);

    return filteredContacts;
}
like image 20
AlBeebe Avatar answered Sep 22 '22 12:09

AlBeebe