oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

A Look Inside Address Book
Pages: 1, 2, 3


A database isn't worth much without a way to search the contents. In address book, the class ABSearchElement is how we create queries with any range of complexity. A search element contains a simple search, like search the address book for all records with the first name Mike, or search for all records with birth dates occurring before the turn of the millennium.

Two or more ABSearchElement objects may be combined into a single composite search elements using either an AND operator or an OR operator. By combining search elements in this way it is possible to build quite complex queries.

Instances of ABSearchElement are created using the ABPerson or ABGroup class method searchElementForProperty:label:key:value:comparison:. Whether we invoke this method in the ABPerson class object or the ABGroup class object depends on whether we want to perform a search for people, or a search for groups. This method takes the following parameters:

  • searchElementForProperty: is the record property the we wish to perform the search again
  • label: If the property is a multi-value property, then we can specify a label here to restrict the search to one particular element of the multi-value
  • key: If the property value is a dictionary, then we can specify a key in the dictionary here to restrict the search.
  • value: This is the value we are searching for
  • comparison: This parameter specifies how the search process will identify a matching value.

The last parameter, comparison:, tells the search element how to determine a matching value. There are ten possible constants to pass here: kABEqual, kABEqualCaseInsensitive, kABLessThan, kABLessThanOrEqual, kABGreaterThan, kABGreaterThanOrEqual, kABContainsSubStringCaseInsensitive, kABPrefixMatch, kABPrefixMatchCaseInsensitive.

To create a composite, or conjunction, search we use the ABSearchElement class method searchElementForConjunction:children:. The first parameter tells the method how the child search elements will be combined. The possible values are kABAndSearch and kABOrSearch. The children: parameter takes an array of ABSearchElements that are to be combined in the conjunction search. Children search elements may be simple searches, or conjunction searches themselves.

The following is an example of searching the address book using search elements:

ABSearchElement *se;
NSArray *results;

se = [ABPerson searchElementForProperty:kABAddressProperty
results = [book recordsMatchingSearchElement:se];  
NSLog( [results description] );

As you can see above, the method recordsMatchingSearchElement: returns an NSArray containing all of the people in the address book whose home address is in Texas.

Performing a conjunction search is done similarly:

ABSearchElement *se1, *se2, *cse;
NSArray *children;

se1 = [ABPerson searchElementForProperty:kABAddressProperty
se2 = [ABPerson searchElementForProperty:kABBirthdayProperty
                        value:[NSDate dateWithTimeIntervalSinceReferenceDate:0]

children = [NSArray arrayWithObjects:se1, se2, nil];

cse = [ABSearchElement searchElementForConjunction:kABAndSearch         

results = [book recordsMatchingSearchElement:cse];
NSLog( [results description] );

The composite search element cse will search for all people in the address book database who not only live in Texas, but who were born before the turn of the millennium, which we specify by creating a date that is zero seconds past the reference date (the absolute reference date used by NSDate is 12:00 AM, January 1, 2001 GMT).

Odds and Ends

To tie up loose ends, let's talk a bit about assigning images to an ABRecord, as well as how we can import and export vCards to and from the AddressBook database.

Creating a vCard is easily accomplished using the ABRecord method vCardRepresentation. This method returns an NSData object whose data is formatted in the vCard format. We can then write this data to disk, which can be read by any number of applications that recognize the vCard format. Going the other way we can initialize an ABRecord object with vCard data using the method initWithVCardRepresentation:. This method takes a parameter an NSData object, which was likely created by reading the contents of a vCard file on disk created by another application.

Finally, to associate an image with a person in the AddressBook we use the methods setTIFFImageData: and TIFFImageData to set and get the person's picture. These methods work with NSData objects whose data is formatted as a TIFF image. This interfaces well with the NSImage methods TIFFRepresentation, which returns an TIFF formatted NSData object, and initWithData:, which initializes an NSImage object with image data.

The End

So, that was a whirlwind tour of the AddressBook framework. It's not really my style to leave you empty-handed at the end of a column, so I've prepared a version of our old-school application Address Book that we worked on about a year ago while learning about NSTableView. This version has been revamped to display the contents of the user's address book in a table, and allow the user to edit records. It's basically the same thing we had before, except the data model is based on ABAddressBook rather than on NSArray and NSDictionary. This is an excellent example of the utility of MVC since the model was separated from the view and insulated by the controller, so it was relatively pain-free to change.

So, happy Jaguar release, and next time we'll get back to those plug-ins.

Michael Beam is a software engineer in the energy industry specializing in seismic application development on Linux with C++ and Qt. He lives in Houston, Texas with his wife and son.

Read more Programming With Cocoa columns.

Return to the Mac DevCenter.