Understanding ABPersonEmailProperty and Email Retrieval in iOS: A Guide to Filtering Facebook Contacts

Understanding ABPersonEmailProperty and Email Retrieval in iOS

As a developer working with Apple’s Address Book (AB) framework, it’s not uncommon to encounter issues with retrieving email addresses for specific contacts. In this article, we’ll delve into the world of ABPersonEmailProperty, explore why some contacts’ email addresses return nil when using kABPersonEmailProperty, and provide a solution to filter out Facebook contacts.

Background: ABRecordCopyValue and CFNumberRef

Before we dive into the code, it’s essential to understand how ABRecordCopyValue works. This method returns a CFPropertyListRef containing the values for a specific key in the contact record. In our case, we’re interested in the email addresses, which are stored under the key kABPersonEmailProperty.

When we use __bridge to convert the CFNumberRef returned by ABRecordCopyValue into an NSNumber object, we need to be aware of the type conversion process. The CFNumberRef can represent either a signed or unsigned integer value.

Filtering Out Facebook Contacts

The problem arises when we try to retrieve email addresses for contacts linked through Facebook. In this scenario, the source type of the contact record is not explicitly set to indicate it’s from Facebook.

To filter out these Facebook contacts, we need to examine the kABSourceTypeProperty value returned by ABRecordCopyValue. This property can take on several values, including:

  • kABSourceTypeLocal: Local contact
  • kABSourceTypeCardDAV: CardDAV source type (may be used for Facebook contacts)
  • kABSourceTypeExchange: Exchange server source type

We’ll use these value comparisons to identify Facebook contacts and filter out their email addresses.

Code Example: Filtering Facebook Contacts

Here’s an example code snippet demonstrating how to filter Facebook contacts:

// Get the person record reference
ABRecordRef person = ABPersonCreate();

// Retrieve the contact's source type
NSNumber *sourceTypeRef = (__bridge NSNumber *)((CFNumberRef)ABRecordCopyValue(person, kABSourceTypeProperty));

if ([sourceTypeRef intValue] == kABSourceTypeCardDAV)
    ; // this is probably, maybe, could be a Facebook contact

else if ([sourceTypeRef intValue] == kABSourceTypeLocal)
    ; // this is definitely a local contact

else if ([sourceTypeRef intValue] == kABSourceTypeExchange)
    ; // this is from an exchange server

// Filter out email addresses for Facebook contacts
NSArray *emailAddresses = (__bridge NSArray*)ABMultiValueCopyArrayOfAllValues((ABMultiValueRef)ABRecordCopyValue(person, kABPersonEmailProperty));

if (![emailAddresses containsObject:@"Facebook Email Address"]) {
    // Retrieve work and home email addresses (optional)
    ABAddressBookAddAddressToGroup(emailAddresses, kABWorkEmailType);
    ABAddressBookAddAddressToGroup(emailAddresses, kABHomeEmailType);
}

Understanding ABMultiValueCopyArrayOfAllValues

In this example, we use ABMultiValueCopyArrayOfAllValues to retrieve an array of all values for the specified key (kABPersonEmailProperty). This method returns a CFArrayRef containing the email addresses as strings.

Note that the __bridge cast is necessary to convert the CFArrayRef to an NSArray*. We’re using this conversion because we want to work with Swift code later on.

Converting CFArrayRef to NSArray*

To convert the CFArrayRef returned by ABMultiValueCopyArrayOfAllValues into an NSArray*, we use a bridging cast. This allows us to access the array elements in our Swift code.

// Retrieve email addresses from ABPersonEmailProperty
ABMultiValueRef emailMultiValue = (ABMultiValueRef)ABRecordCopyValue(person, kABPersonEmailProperty);
NSArray *emailAddresses = (__bridge NSArray*)ABMultiValueCopyArrayOfAllValues(emailMultiValue);

// Do something with the emailAddresses array...

Conclusion

In this article, we explored how to retrieve email addresses for specific contacts using kABPersonEmailProperty. By examining the source type of the contact record and filtering out Facebook contacts, we can ensure that our app only returns relevant email addresses.

When working with Apple’s Address Book framework, it’s essential to understand how ABRecordCopyValue and CFNumberRef work. Additionally, using bridging casts helps convert between Core Foundation and Objective-C types, making it easier to integrate Swift code into your apps.

Remember to always consider the type conversions involved when working with these frameworks.


Last modified on 2023-11-23