macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

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

Records

A record is the fundamental collection of information in the AddressBook. Records can either be people, ABPerson; or groups, ABGroup. ABRecord is itself an abstract class, and is thus never instantiated. Records contain properties and values, which is similar to NSDictionary's use of keys and objects.



An array of all of the people in an address book is obtained by sending a people message to our ABAddressBook object. Similarly, we can send a groups message to the address book object to get an array containing the groups in the address book.

NSArray *everyone = [book people];
NSArray *everygroup = [book groups];

NSLog( [everyone description] );
NSLog( [everygroup description] );

This will print out the property list representation of the arrays everyone, and everyoneElse, which are respectively the top-level groups and people in the address book. The arrays actually contain ABPerson and ABGroup objects, one for each record. Using the people and groups methods is the quick way into the address book, useful if you want to present the user with a list of available contacts, such as is done in iChat.

A special kind of record in the address book is the record that identifies the current user, or "Me". This record is retrieved from the ABAddressBook object by sending it a me message. It is also possible to change "me" by invoking the method setMe:.

ABPerson *me = [book me];
NSLog( [me description] );

New records are created by instantiating either ABPerson or ABGroup, which is done using alloc and init. When a new record is created, it's given a unique id, which is stored in the kABUIDProperty defined in ABRecord. Once you have a new record object, you can add it to the address book using the ABAddressBook method addRecord:. If you want to remove a record, you may do so by sending a removeRecord: message to the address book object.

Related Reading

Building Cocoa Applications: A Step by Step Guide
By Simson Garfinkel, Michael Mahoney

Changes to the address book, including the addition or removal of records, are not made permanent (i.e. not written to file) until the save method of ABAddressBook is invoked. You can inquire into the existence of unsaved changes using the method hasUnsavedChanges.

Properties and Values

With the basics of working with records under our belt, it's time to learn how to manipulate the information contained within the record, which is why we're here after all. The first thing one would want to do is determine what's in the record. Property values are accessed using the NSDictionary-inspired method of ABRecord valueForProperty:. This method takes an NSString property name, and returns the value for that property. To set the value of a property we use the method setValue:forProperty:.

AddressBook defines the following list of NSString constants that identify the properties that a person may take on:

  • kABFirstNameProperty
  • kABLastNameProperty
  • kABFirstNamePhoneticProperty
  • kABLastNamePhoneticProperty
  • kABBirthdayProperty
  • kABOrganizationProperty
  • kABJobTitleProperty
  • kABHomePageProperty
  • kABEmailProperty
  • kABAddressProperty
  • kABPhoneProperty
  • kABAIMInstantProperty
  • kABJabberInstantProperty
  • kABMSNInstantProperty
  • kABYahooInstantProperty
  • kABICQInstantProperty
  • kABNoteProperty
  • kABMiddleNameProperty
  • kABMiddleNamePhoneticProperty
  • kABTitleProperty
  • kABSuffixProperty
  • kABNicknameProperty
  • kABMaidenNameProperty

The list above applies only to ABPerson type records. Note that the last six properties in the list above are not supported in the Address Book user interface -- so you can use them, but you won't see any evidence of their existence in Address Book. ABGroup type records have only one property: kABGroupNameProperty. Both people and groups have the following properties, that are part of ABRecord:

  • kABUIDProperty
  • kABCreationDateProperty
  • kABModificationDateProperty

The values of properties may be any of the supported property list data types: strings, numbers, dictionaries, dates, and data. Additionally, a property value may be an ABMultiValue data type, which is how AddressBook stores multiple values for a single property. Multiple values will be discussed at greater length below. In the list of ABPerson properties, all of the instant message properties are multivalue, as are the email, address, and phone number properties. The remainder are dates or strings.

The example below demonstrates how we can work with properties.

NSArray *everyone = [book people];
ABPerson *someone = [everyone objectAtIndex:0];

NSLog( [someone valueForProperty:kABFirstNameProperty] );
NSLog( [someone valueForProperty:kABLastNamePropertu] );

[someone setValue:@"Pete" forProperty:kABFirstNameProperty];

if ( [book hasUnsavedChanges] ) 
    [book save];

Multi-value Properties

Many property values in the AddressBook are typed as ABMultiValue, which is an object that stores multiple values for a single property. The idea behind ABMultiValue is that for many attributes of a person, such as phone numbers, email addresses, and address there exist multiple values. For example, most people have different addresses, phone numbers, and email addresses for their home and work. So rather than create several scattered properties for a work and home properties, AddressBook uses ABMultiValue which may contain an arbitrary number of values. This is by far a more flexible and cleaner solution.

An ABMultiValuee stores the multiple values for a property by index. Associated with each is a unique identifier, a string label, and a value. Generally, the label is some variant of home and work, such as kABAddressHomeLabel and kABAddressWorkLabel for the address property multi-value. However, it is possible to designate labels for additional values in the multi-value object beyond those for home and work (i.e. A summer vacation home address in addition to home and work). Additionally, while there are home and work labels specific to each multi-value property -- kABXXXXWorkLabel and kABXXXXHomeLabel -- AddressBook also defines the generic labels kABWorkLabel, kABHomeLabel, and kABOtherLabel which are equivalent to the property specific labels.

Every multi-value property has what is known as a primary identifier. The primary identifier identifies the sub value of the multi-value property that is most strongly associated with the person. For example, if you interact with a person purely on a professional basis, the primary identifier for that contact in your AddressBook would be for the work value of the contacts various properties. This identifier can be set in a ABMutableMultiValue using the instance method setPrimaryIdentifier:. Each multi-value property may have a different primary identifier.

Values are accessed in an ABMultiValue object by index using the method valueAtIndex:. If we wanted to access the primary value of the multi-value, we could do so by passing the primary identifier string -- obtained with the primaryIdentifier method -- to the method indexForIdentifier:. This returned index is then passed to valueAtIndex:.

To demonstrate how multi-value objects are used, let's take a closer look at the kABAddressBookProperty, a particularly interesting property since it contains NSDictionary objects rather than simple strings. The members of the address dictionary contain all of the pertinent address information such as street number and state. The following list is a list of the keys used to access values in the address dictionaries in the ABMultiValue object for kABAddressProperty.

  • kABAddressStreetKey -- The person's street name and number
  • kABAddressCityKey -- The person's city
  • kABAddressStateKey -- The person's state
  • kABAddressZIPKey -- The zip code of the address
  • kABAddressCountryKey -- The country name of the address
  • kABAddressCountryCodeKey -- The two character country code. These are standard ISO country codes, and can be found in the header file ABGlobals.h.

Let's take a look at some examples of how we access multi-value properties:

ABMultiValue *addrs = [[book me] valueForProperty:kABAddressProperty];

int count = [addrs count];  // Determining the number of values

NSDictionary *addr = [addrs valueAtIndex:0];

NSString *primaryID = [addrs primaryIdentifier];
int idx = [addrs indexForIdentifier:primaryID]
NSDictionary *primaryAddr = [addrs valueAtIndex:idx];
NSString *primaryLabel = [addrs labelAtIndex:idx];

NSString *city = [primaryAddr objectForKey:kABAddressCityKey];

Defining New Properties

The AddressBook database is extensible, that is, an application can create additional properties for ABPerson objects and store information in those properties. Adding new properties will not disturb the way other applications interact with the Address Book -- what they don't know won't hurt them.

To add new properties we first create an NSDictionary whose keys are the property names, like kABFirstNameProperty, and the object for that key is the property type. AddressBook supports the following property types:

  • kABStringProperty or kABMultiStringProperty
  • kABIntegerProperty or kABMultiIntegerProperty
  • kABRealProperty or kABMultiRealProperty: a floating point number
  • kABDateProperty or kABMultiDateProperty: NSDate
  • kABArrayProperty or kABMultiArrayProperty: NSArray
  • kABDictionaryProperty or kABMultiDictionaryProperty: NSDictionary
  • kABDataProperty or kABMultiDataProperty: NSData

Since property names must be unique, it is best to adopt some naming convention such as is done with preference files: Java-style package naming. Once we have assembled our dictionary of property names and types, we pass it as a parameter to the ABPerson class method addPropertiesAndTypes:. Here is an example of this:

ABPerson *me = [book me];

NSMutableDictionary *new = [NSMutableDictionary dictionary]
[new setObject:@"kABStringProperty" forKey:@"com.myCompany.collegeProperty"];
[new setObject:@"kABDateProperty" forKey:@"com.myCompany.graduationDate];

[me setValue:@"The University of Texas"     
            forProperty::@"com.myCompany.collegeProperty"];

Because addPropertiesAndTypes: is a class method, it makes the property available for every person in the address book. Because of this, you should be judicious when adding new properties to make sure that it is applicable to a majority of the people in the address book. In other words, don't add address book properties if they only apply to one person in the database. For that, NSUserDefaults is a better solution.

Adding properties using addPropertiesAndTypes: has no effect if the property exists already with the specified type. Additionally, once a property has been added, is accessible just as any property. There is no need to add the property before attempting to access the value, or anything like that. You only need to add it the first time.

If you would like to remove a custom property completely, then you can do so using the ABPerson method removeProperties:. This method takes an NSArray containing all of the property names of the properties you would like removed. It returns the number of properties that were successfully removed.

Pages: 1, 2, 3

Next Pagearrow