iOS: How To Get The Person Out Of ABAddressBookRef

One of the reasons I made an offer to build an iPhone app for anyone for $200 was so I could continue learning. The more variety in the projects, the better, since that means I get to experiment with different parts of the iOS SDK.

Currently, I’m working on an app that requires me to use and store address book contacts. Seems like something that should be pretty simple, right?! Well, that’s what I though until I started working with ABAddressBookRef. To my surprise, working with ABAddressBookRef is more like working with C instead of Objective-C. Times like this is when I wish I’d taken Stanford’s CS107A. Maybe I still will!

Anyway, after a bit of struggle, I wanted to share how I got the person’s name and record id from the address book, so I could store it in locally in the app I’m building.

// ViewController.m

#import "ViewController.h"

// make sure to import the AddressBook framework
#import <AddressBook/AddressBook.h>

// I'm using Core Data to store the Person locally
// this is my Person category
#import "Person+WOLExtensions.h"

@implementation ViewController
- (void)viewDidLoad
    [super viewDidLoad];

    [self loadPeopleFromAddressBook];

- (void)loadPeopleFromAddressBook
    CFErrorRef error = nil;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    [Person retrievePeopleFromAddressBook:addressBook];

// your other custom implementation here

// Person+WOLExtensions.m

#import "Person+WOLExtensions.h"

@implementation Person (WOLExtensions)

+ (void)retrievePeopleFromAddressBook:(ABAddressBookRef)addressBook
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        if (error || !granted)
            // handle error
            NSLog(@"ERROR: %@", error);
            CFArrayRef peopleFromAddressBook = ABAddressBookCopyArrayOfAllPeople(addressBook);
            CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

            // using Magical Record to get all the people from CoreData
            NSArray *peopleArray = [Person MR_findAll];

            for (int i = 0; i < numberOfPeople; i++) {

                ABRecordRef personRecord = CFArrayGetValueAtIndex(peopleFromAddressBook, i);

                NSNumber *recordId = [Person recordIdFromPersonRecord:personRecord];

                if ([self isUniqueRecord:recordId peopleArray:peopleArray])
                    Person *person = [Person MR_createEntity];
                    person.recordId = recordId;
           = [Person nameFromPersonRecord:personRecord];


        [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveWithOptions:MRSaveParentContexts completion:nil];

+ (BOOL)isUniqueRecord:(NSNumber *)recordId peopleArray:(NSArray *)peopleArray
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"recordId = %@", recordId];
    NSArray *duplicates = [peopleArray filteredArrayUsingPredicate:predicate];
    return duplicates.count == 0;

+ (NSNumber *)recordIdFromPersonRecord:(ABRecordRef)personRecord
    ABRecordID recordId = ABRecordGetRecordID(personRecord);
    return [NSNumber numberWithInt:(int)recordId];

+ (NSString *)nameFromPersonRecord:(ABRecordRef)personRecord
    ABMultiValueRef name = ABRecordCopyCompositeName(personRecord);
    return (__bridge NSString *)name;

If you can think of a better way to do this, please let me know in the comments?

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.