MOBILE

Iphone SDK : Working with the Address Book Database - Accessing Multi-Value Properties

9/30/2012 2:34:10 AM
In this section, we talk about the manipulation of multi-value properties.

1. Retrieving multi-value properties

To retrieve the value of a multi-value property, you use the same function you used to retrieve a single-value property, ABRecordCopyValue. The value returned is of type ABMultiValueRef which is declared as an alias to the generic CFTypeRef type.

The following shows how to retrieve the person's emails:

ABMultiValueRef emailsProperty =
                    ABRecordCopyValue(person, kABPersonEmailProperty);

Once we have the multi-value object, we can retrieve its values (in this case, the strings of emails), using the function ABMultiValueCopyArrayOfAllValues, which is declared as follows:

CFArrayRef ABMultiValueCopyArrayOfAllValues(ABMultiValueRef multiValue);

The function returns the values in an NSArray object. You can then iterate through this array and access the values.

Each value stored for a multi-value property has a label identifying this value and a unique identifier. The label can be any string value, and several values can have the same label. Some of the generic labels defined are: kABWorkLabel, kABHomeLabel, and kABOtherLabel.

To retrieve the label for a given value, you can use the ABMultiValueCopyLabelAtIndex function. It returns an NSString object with the label of a given value. The function is declared as follows:

CFStringRef ABMultiValueCopyLabelAtIndex(
                ABMultiValueRef multiValue, CFIndex index);

The first parameter is the multi-value object and the second is the index of the value whose label you want to retrieve. For example, the following retrieves the label value for the email at index:

NSString  *emailLabel =
        (NSString*)ABMultiValueCopyLabelAtIndex(emailsProperty, index);

As usual, since the function has a "copy" in it, you are responsible for the object's memory.

The following are some of the multi-value property identifiers defined for the person record:

  • kABPersonAddressProperty. This identifier is used to access the person's address multi-value property. The property type is kABMultiDictionaryPropertyType, which means that each value of this property is an NSDictionary instance.

  • kABPersonDateProperty. This identifier is used to access all the dates associated with this person. Each value is an NSDate instance.

  • kABPersonPhoneProperty. This identifier is used to retrieve all phone numbers associated with the person. Each value is an NSString instance.

  • kABPersonURLProperty. This identifies all the URLs associated with this person. Each value is an NSString object.

Listing 1 shows a code fragment that retrieves all the emails of a given person and logs them labelled.

Example 1. Logging all the emails associated with a given person record.
//Access  emails 
 ABMultiValueRef emailsProperty =
      ABRecordCopyValue(person, kABPersonEmailProperty);
 NSArray* emailsArray =
     (NSArray*)ABMultiValueCopyArrayOfAllValues(emailsProperty);
 NSLog(@"Emails:");
 for (int  index = 0; index< [emailsArray count]; index++){
   NSString  *email = [emailsArray objectAtIndex:index];
   NSString  *emailLabel =
      (NSString*)ABMultiValueCopyLabelAtIndex(emailsProperty, index);
   NSLog(@"%@: %@",
     [emailLabel isEqualToString:(NSString*)kABWorkLabel]?@"Work":
     [emailLabel isEqualToString:(NSString*)kABHomeLabel]?
         @"Home":@"Other", email);
   [emailLabel release];
 }
 CFRelease(emailsProperty);
 [emailsArray release];

Listing 2 shows a code fragment that retrieves all the phone numbers of a given person and logs them labelled.

Example 2. Logging all the phone numbers associated with a given person record.
// Access  phones 
  ABMultiValueRef phonesProperty =
      ABRecordCopyValue(person, kABPersonPhoneProperty);
  NSArray* phonesArray =
      (NSArray*)ABMultiValueCopyArrayOfAllValues(phonesProperty);
  NSLog(@"Phones:");
  for (int  index = 0; index< [phonesArray count]; index++){
    NSString *aPhone = [phonesArray objectAtIndex:index];
    NSString  *phoneLabel =
      (NSString*)ABMultiValueCopyLabelAtIndex(phonesProperty, index);
    NSLog(@"%@: %@",
     [phoneLabel isEqualToString:(NSString*)kABPersonPhoneMobileLabel]?
                 @"Mobile":@"Phone", aPhone);
    [phoneLabel release];
  }
  CFRelease(phonesProperty);
  [phonesArray release];
}

2. Setting multi-value properties

To modify a multi-value property, you need a mutable version of that property. If you want to create a brand new value, you use ABMultiValueCreateMutable function, add the values and labels to it and set the corresponding property with the new value. If, on the other hand, you want to modify an existing multi-value, you retrieve this value, create a mutable copy of it using the function ABMultiValueCreateMutableCopy, add to or delete from it, and set the value in the record.

Let's make these steps concrete through some examples. First, let's us look at creating a brand new multi-value.

We want to set a person's record with one work address. First, we create a mutable multi-value as follows:

ABMutableMultiValueRef multiValueAddress =
    ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);

Here, we are asking the address book framework to create a new multi-value object of kABMultiDictionaryPropertyType type. As we mentioned before, this is the type of the street address property (a person can have multiple addresses and each address is a dictionary).

After that, we create one address and store its parts in a dictionary as follows:

NSMutableDictionary *theAddress =
    [[[NSMutableDictionary alloc] init] autorelease];
  [theAddress setValue:@"1600 Pennsylvania Avenue NW"
    forKey:(NSString *)kABPersonAddressStreetKey];
  [theAddress setValue:@"Washington"
    forKey:(NSString *)kABPersonAddressCityKey];
  [theAddress setValue:@"DC"
    forKey:(NSString *)kABPersonAddressStateKey];
  [theAddress setValue:@"20500"
    forKey:(NSString *)kABPersonAddressZIPKey];
  [theAddress setValue:@"us"
    forKey:(NSString *)kABPersonAddressCountryCodeKey];

This is pretty straight-forward dictionary creation. The keys used are defined by the framework. You can set any or all of them as they are all optional.

Now that we have a new value, we need to add it to the multi-value and give it a label. The function to use is ABMultiValueAddValueAndLabel. The first parameter of this function is the multi-value object, the second is the value to add, and the third is the label. You can pass a reference to an NSError object if you want to in the fourth parameter. The following shows the addition of the new address to the multi-value object:

ABMultiValueAddValueAndLabel(multiValueAddress, theAddress,
                             kABWorkLabel, NULL);

You can repeat these steps for each additional address. Once you have what you want, you set the multi-value property with the new value using our old friend ABRecordSetValue as follows:

ABRecordSetValue(person,kABPersonAddressProperty,multiValueAddress,NULL);

If, on the other hand, you want to modify an existing multi-value, you need to retrieve it, create a mutable copy of it, add to the mutable copy, and set it back to the record. The following code fragment shows exactly that:

ABMultiValueRef streetAddressProperty =
  ABRecordCopyValue(person, kABPersonAddressProperty);
ABMutableMultiValueRef mutableStreetAddressProperty =
  ABMultiValueCreateMutableCopy(streetAddressProperty);
CFRelease(streetAddressProperty);
NSMutableDictionary *theAddress =
  [[[NSMutableDictionary alloc] init] autorelease];
[theAddress setValue:@"1600 Pennsylvania Avenue NW"
  forKey:(NSString *)kABPersonAddressStreetKey];
[theAddress setValue:@"Washington"
  forKey:(NSString *)kABPersonAddressCityKey];
[theAddress setValue:@"DC"
  forKey:(NSString *)kABPersonAddressStateKey];
[theAddress setValue:@"20500"
  forKey:(NSString *)kABPersonAddressZIPKey];
[theAddress setValue:@"us"
  forKey:(NSString *)kABPersonAddressCountryCodeKey];
ABMultiValueAddValueAndLabel(mutableStreetAddressProperty,
  theAddress, kABHomeLabel, NULL);
ABRecordSetValue(person, kABPersonAddressProperty,
  mutableStreetAddressProperty, NULL);
CFRelease(mutableStreetAddressProperty);					  
Other  
 
Top 10
Review : Sigma 24mm f/1.4 DG HSM Art
Review : Canon EF11-24mm f/4L USM
Review : Creative Sound Blaster Roar 2
Review : Philips Fidelio M2L
Review : Alienware 17 - Dell's Alienware laptops
Review Smartwatch : Wellograph
Review : Xiaomi Redmi 2
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
VIDEO TUTORIAL
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone