Searching an Address Book

You can quickly search a user’s address book, using arbitrarily complex criteria. For example, you can search for all people named Smith, or for all people who work at Acme and live in San Francisco, or for all people who work at Ajax and live in Seattle.

To perform the search, you encapsulate the criteria in a search element to pass it to the Address Book framework. The framework performs the search on your behalf, and returns the results. Letting the framework handle the search can yield significant performance benefits compared to performing the search inside your application, because the framework is aware of the low-level layout of the underlying database, and it can optimize disk access accordingly.

Creating a Search Element for a Single Property

To create a search element for a person, use the ABPerson class method searchElementForProperty:label:key:value:comparison:. To create a search element for a group, use the ABGroup class method searchElementForProperty:label:key:value:comparison:.

If you want to search for people or groups that have a particular property set, regardless of the value it is set to, pass nil as the value and kABNotEqual as the comparison. To search for people or groups that do not have a property set, pass nil as the value and kABEqual as the comparison.

Creating a Search Element for Multiple Properties

To combine search elements, use the ABSearchElement class method searchElementForConjunction:children:. This method takes two arguments:

Finding Records That Match a Search Element

To search the address book for records that match a search element, use the ABAddressBook method recordsMatchingSearchElement:, which returns an NSArray of records. Use the ABSearchElement method matchesRecord: to test whether a specific record matches a query.

Search Examples

Listing 1 shows the code to find everyone whose last name is Smith.

Listing 1  A simple search

ABAddressBook *AB = [ABAddressBook sharedAddressBook];
ABSearchElement *nameIsSmith =
    [ABPerson searchElementForProperty:kABLastNameProperty
                                 label:nil
                                   key:nil
                                 value:@"Smith"
                            comparison:kABEqualCaseInsensitive];
NSArray *peopleFound =
    [AB recordsMatchingSearchElement:nameIsSmith];

Listing 2 shows the code to find everyone who lives in San Francisco and works for Acme, or who lives in Seattle and works for Ajax. Note that the addresses are searched using the kABHomeLabel label—we only want to know if they live in the city we are searching, not if they work in the same city.

Listing 2  A complex search

ABAddressBook *AB = [ABAddressBook sharedAddressBook];
ABSearchElement *inSF =
    [ABPerson searchElementForProperty:kABAddressProperty
                                 label:kABHomeLabel
                                   key:kABAddressCityKey
                                 value:@"San Francisco"
                            comparison:kABEqualCaseInsensitive];
ABSearchElement *atAcme =
    [ABPerson searchElementForProperty:kABOrganizationProperty
                                 label:nil
                                   key:nil
                                 value:@"Acme"
                            comparison:kABContainsSubStringCaseInsensitive];
ABSearchElement *inSeattle =
    [ABPerson searchElementForProperty:kABAddressProperty
                                 label:kABHomeLabel
                                   key:kABAddressCityKey
                                 value:@"Seattle"
                            comparison:kABEqualCaseInsensitive];
ABSearchElement *atAjax =
    [ABPerson searchElementForProperty:kABOrganizationProperty
                                 label:nil
                                   key:nil
                                 value:@"Ajax"
                            comparison:kABContainsSubStringCaseInsensitive];
ABSearchElement *inSFAndAtAcme =
    [ABSearchElement searchElementForConjunction:kABSearchAnd
                                        children:[NSArray arrayWithObjects:
                                            inSF, atAcme, nil]];
ABSearchElement *inSeattleAndAtAjax =
    [ABSearchElement searchElementForConjunction:kABSearchAnd
                                        children:[NSArray arrayWithObjects:
                                            inSeattle, atAjax, nil]];
ABSearchElement *inSFAndAtAcmeOrInSeattleAndAtAjax =
    [ABSearchElement searchElementForConjunction:kABSearchOr
                                        children:[NSArray arrayWithObjects:
                                            inSFAndAtAcme, inSeattleAndAtAjax, nil]];
NSArray *peopleFound =
    [AB recordsMatchingSearchElement:inSFAndAtAcmeOrInSeattleAndAtAjax];