oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Programming With Cocoa A Look Inside Address Book

by Michael Beam, O'Reilly Mac OS X Conference Speaker

A Look Inside Address Book

Now that Jaguar is out, let's take a break from our recent series of graphics columns and look into one of the many new features of Mac OS X, version 10.2 that we Cocoa developers might be interested in: the AddressBook framework.

Prior to Jaguar, the Address Book application, and the collection of contacts contained within it, was an island of information that only a few privileged applications were able to access (Mail, in particular). However, with Jaguar, Apple has created a system-wide database of a user's contacts, and has provided an Objective-C API for accessing that database. This makes it possible for any number of third-party applications to not only access the contents of the address book database, but to perform any action on the contacts that may be done in Address Book, and more ....

Note: In this column when I say Address Book, with a space, I am referring to the application. AddressBook without a space refers to the framework, and finally, address book refers to the database.

If you're developing a Mac application that uses information about people, then I can't recommend highly enough integrating AddressBook into your software. This will prevent your application from being isolated from a feature that's becoming a core component of Mac OS X. As you'll see in this column, using the AddressBook framework is likely an easier task than implementing your own data model and your system of managing contacts. You'll also see how the database is extensible so that it can contain information specific to your application, without polluting other applications' use of the database.

As an example of how AddressBook can be integrated into an application, let's take a look at how iChat does it. If you open up iChat, you will see in your buddy list all of your AIM buddies. It's possible to assign information to a buddy, such as a person's real name, email address, and more. Now, rather than forcing you to enter this information by hand, iChat provides a button that pops up a dialog with a list of all your contacts in the AddressBook database. From this list you can select who you want to associate with the selected screen name. The information can then be synchronized in both directions, that is, Address Book will update its information about the contact to include the selected screen name, and iChat will display the person's real name rather than the screen name.

If you're not a fan of AIM, never fear. As you'll soon see, AddressBook provides built-in fields for not only AIM screen names, but also those for MSN, Jabber, and Yahoo. Thus, it is possible to achieve the same level of integration with AddressBook present in iChat in other applications such as Proteus, Fire, Adium, and MSN Messenger (if the developers choose to do so).

So, that's a quick look at where AddressBook can take us, feature-wise. Now let's now take a look to see how it's organized and how we can work with it all.

The Lay of the Land

The AddressBook framework stores information in a property list file for each user. Here we're already on familiar ground, as it is the same format for user defaults as well as data structures like arrays, dictionaries, strings, and numbers. This is, however, of trivial importance. All we care about is how to interact with the database.

The entry point to the system is through the class ABAddressBook, which we instantiate using the class method sharedAddressBook. From here we can access all of the address book records and also create new ones.

Records in the address book are instances of the class ABPerson or ABGroup, both of which inherit from the class ABRecord. ABPerson represents a single person and contains properties identifying information about that person, such as his email address, birthday, name, phone numbers, addresses, and more.

A group, on the other hand, is a collection of people and other groups. An ABGroup contains any number of people or additional groups, and carries only one property beyond those provided by ABRecord--the group name.

To access the contents of the address book, we have several options. We can make ABAddressBook return an array of all the people or all the groups it knows about by invoking the method people and groups, respectively. It is also possible to search the address book for a specific record or records matching some search criteria. Queries are created using the class ABSearchElement, which is then passed to the ABAddressBook instance to get the results of the search.

Download the application files for this article here.

To kick the tires of this framework we're going to go simple and code in a basic foundation tool. All of our output information will be displayed in the standard output in the run tab using NSLog, and the goal here is to just play around with the framework. We won't end up with an application at the conclusion, as we usually do.

Since the AddressBook framework is new to Jaguar, you have to have 10.2 installed to run these examples. To start out, create a new project from the File menu that is now a Foundation Tool. Now we have to add the AddressBook framework to the project and import the headers into our main source file. From the Project menu select Add Frameworks ... ; navigate to the /System/Library/Frameworks directory; and select AddressBook.framework. (This will only be present in Mac OS X 10.2. Additionally, you must have the most recent developer tools installed, or else you will get compilation errors.)

Be sure to add to the source file main.m the import statement:

#import <AddressBook/AddressBook.h>

To work with the framework, it's best to have several contacts in your address book. If you don't, then go ahead and open up Address Book and add some people to your address book and create a group or two if none exist yet.

Starting out with our Foundation tool all we have is a main function that creates an autorelease pool, does the whole "Hello, World" job, destroys the autorelease pool, then returns. The printf statement will be taken out and in its place we will put all of the code we wish to experiment with.

The first thing we want to do is instantiate ABAddressBook:

int main (int argc, const char *argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    ABAddressBook *book = [ABAddressBook sharedAddressBook];
    [pool release];
    return 0;

All of our test code from now on will go between where we instantiate ABAddressBook and where we release pool. With this in place let's work our way through the framework and see what we learn.

Pages: 1, 2, 3

Next Pagearrow