Home » Ios » Get a list of all contacts on iOS

Get a list of all contacts on iOS

Posted by: admin November 30, 2017 Leave a comment

Questions:

I want to get a list of all contacts of an iPhone.

I checked Address Book reference, I may missed something but I didn’t see it provides a method to get a list of contacts.

Answers:

Perhaps ABPerson function ABAddressBookCopyArrayOfAllPeople might do?

Example:

ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );

for ( int i = 0; i < nPeople; i++ )
{
    ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
    ...
}

Questions:
Answers:

In my original answer, at the end of this answer, I show how to retrieve contacts in iOS versions prior to 9.0 in a manner that addresses some of the problems entailed by other answers here.

But, if only supporting iOS 9 and later, one should use the Contacts framework, avoiding some of the annoying bridging issues entailed when using the older AddressBook framework.

So, in iOS 9, you’d use the Contacts framework:

@import Contacts;

You also need to update your Info.plist, adding a NSContactsUsageDescription to explain why your app requires access to contacts.

And then do something like follows:

CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted) {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Access to contacts." message:@"This app requires access to contacts because ..." preferredStyle:UIAlertControllerStyleActionSheet];
    [alert addAction:[UIAlertAction actionWithTitle:@"Go to Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
    }]];
    [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
    [self presentViewController:alert animated:TRUE completion:nil];
    return;
}

CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {

    // make sure the user granted us access

    if (!granted) {
        dispatch_async(dispatch_get_main_queue(), ^{
            // user didn't grant access;
            // so, again, tell user here why app needs permissions in order  to do it's job;
            // this is dispatched to the main queue because this request could be running on background thread
        });
        return;
    }

    // build array of contacts

    NSMutableArray *contacts = [NSMutableArray array];

    NSError *fetchError;
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];

    BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) {
        [contacts addObject:contact];
    }];
    if (!success) {
        NSLog(@"error = %@", fetchError);
    }

    // you can now do something with the list of contacts, for example, to show the names

    CNContactFormatter *formatter = [[CNContactFormatter alloc] init];

    for (CNContact *contact in contacts) {
        NSString *string = [formatter stringFromContact:contact];
        NSLog(@"contact = %@", string);
    }
}];

Below is my answer applicable if supporting iOS versions prior to iOS 9.0.

A couple of reactions to not only your question, but also many of the answers provided here (which either fail to request permission, don’t handle ABAddressBookCreateWithOptions errors properly, or leak):

  1. Obviously, import the AddressBook framework:

    #import <AddressBook/AddressBook.h>
    

    or

    @import AddressBook;
    
  2. You must request permission for the app to access the contacts. For example:

    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
    
    if (status == kABAuthorizationStatusDenied || status == kABAuthorizationStatusRestricted) {
        // if you got here, user had previously denied/revoked permission for your
        // app to access the contacts and all you can do is handle this gracefully,
        // perhaps telling the user that they have to go to settings to grant access
        // to contacts
    
        [[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        return;
    }
    
    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    
    if (!addressBook) {
        NSLog(@"ABAddressBookCreateWithOptions error: %@", CFBridgingRelease(error));
        return;
    }
    
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        if (error) {
            NSLog(@"ABAddressBookRequestAccessWithCompletion error: %@", CFBridgingRelease(error));
        }
    
        if (granted) {
            // if they gave you permission, then just carry on
    
            [self listPeopleInAddressBook:addressBook];
        } else {
            // however, if they didn't give you permission, handle it gracefully, for example...
    
            dispatch_async(dispatch_get_main_queue(), ^{
                // BTW, this is not on the main thread, so dispatch UI updates back to the main queue
    
                [[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
            });
        }
    
        CFRelease(addressBook);
    });
    
  3. Note that above, I have not used the pattern suggested by others:

    CFErrorRef *error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    

    That is not correct. As you’ll see above, you want:

    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    

    The former pattern will not capture the error correctly, whereas the latter will. If error was not NULL, don’t forget to CFRelease it (or transfer ownership to ARC like I did) or else you’ll leak that object.

  4. To iterate through the contacts, you want to:

    - (void)listPeopleInAddressBook:(ABAddressBookRef)addressBook
    {
        NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
        NSInteger numberOfPeople = [allPeople count];
    
        for (NSInteger i = 0; i < numberOfPeople; i++) {
            ABRecordRef person = (__bridge ABRecordRef)allPeople[i];
    
            NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
            NSString *lastName  = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
            NSLog(@"Name:%@ %@", firstName, lastName);
    
            ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
    
            CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
            for (CFIndex j = 0; j < numberOfPhoneNumbers; j++) {
                NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, j));
                NSLog(@"  phone:%@", phoneNumber);
            }
    
            CFRelease(phoneNumbers);
    
            NSLog(@"=============================================");
        }
    }
    
  5. I want to draw your attention to a fairly key detail, namely the “Create Rule”:

    Core Foundation functions have names that indicate when you own a returned object:

    • Object-creation functions that have “Create” embedded in the name;

    • Object-duplication functions that have “Copy” embedded in the name.

    If you own an object, it is your responsibility to relinquish ownership (using CFRelease) when you have finished with it.

    This means that you bear responsibility for releasing any object returned by any Core Foundation function with Create or Copy in the name. You can either call CFRelease explicitly (as I did above with addressBook and phoneNumbers) or, for objects that support toll-free bridging, you can transfer ownership to ARC with __bridge_transfer or CFBridgingRelease (as I did above with allPeople, lastName, firstName, and phoneNumber).

    The static analyzer (press shift+command+B in Xcode or choose “Analyze” from the “Product” menu) can identify many situations in which you neglected to observe this “Create Rule” and failed to release the appropriate objects. So, whenever writing Core Foundation code like this, always run it through the static analyzer to make sure you don’t have any obvious leaks.

Questions:
Answers:

Use this code to display all names + lastnames + phonenumbers (iOS 6). Works on simulator too:

CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

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

    ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );

    NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
    NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
    NSLog(@"Name:%@ %@", firstName, lastName);

    ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);

    for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
        NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
        NSLog(@"phone:%@", phoneNumber);
    }

    NSLog(@"=============================================");

}

Questions:
Answers:

Make sure you have the proper import

#import <AddressBook/AddressBook.h>

Then you can get a CFArray object with all contacts using

CFArrayRef ABAddressBookCopyArrayOfAllPeople (ABAddressBookRef addressBook);

Questions:
Answers:

In iOS 6, make sure you use ABAddressBookCreateWithOptions, which is the updated version of ABAddressBookCreate

CFErrorRef * error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

for(int i = 0; i < numberOfPeople; i++){
  ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
  // More code here
}

Questions:
Answers:

Update for iOS 9.0. Apple has deprecated AddressBook and now they have added Contacts framework:

Add CNContactStore property and define it like this:

self.contactsStrore = [[CNContactStore alloc] init];

Then add these methods to read all contacts:

-(void)checkContactsAccess{

[self requestContactsAccessWithHandler:^(BOOL grandted) {

    if (grandted) {

        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNamePrefixKey, CNContactMiddleNameKey, CNContactPhoneNumbersKey]];
        [self.contactsStrore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {

            NSLog(@"%@", contact.familyName);
            NSLog(@"%@", contact.givenName);
            NSLog(@"%@", contact.namePrefix);
            NSLog(@"%@", contact.middleName);
            NSLog(@"%@", contact.phoneNumbers);
            NSLog(@"=============================================");
        }];
    }
}];
}

-(void)requestContactsAccessWithHandler:(void (^)(BOOL grandted))handler{

switch ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]) {
    case CNAuthorizationStatusAuthorized:
        handler(YES);
        break;
    case CNAuthorizationStatusDenied:
    case CNAuthorizationStatusNotDetermined:{
        [self.contactsStrore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {

            handler(granted);
        }];
        break;
    }
    case CNAuthorizationStatusRestricted:
        handler(NO);
        break;
}
}

Before iOS 9.0 => Use AddressBook framework.
You have to check for access and request access to User contacts first:

// Prompt the user for access to their Address Book data
-(void)requestAddressBookAccess
{
   YourViewController * __weak weakSelf = self;

  ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error)
                                         {
                                             if (granted)
                                             {
                                                 dispatch_async(dispatch_get_main_queue(), ^{
                                                     [weakSelf accessGrantedForAddressBook];

                                                 });
                                             }
                                         });
}



-(void)checkAddressBookAccess
{
   switch (ABAddressBookGetAuthorizationStatus())
       {
        // Update our UI if the user has granted access to their Contacts
    case  kABAuthorizationStatusAuthorized:
        [self accessGrantedForAddressBook];
        break;
        // Prompt the user for access to Contacts if there is no definitive answer
    case  kABAuthorizationStatusNotDetermined :
        [self requestAddressBookAccess];
        break;
        // Display a message if the user has denied or restricted access to Contacts
    case  kABAuthorizationStatusDenied:
    case  kABAuthorizationStatusRestricted:
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Privacy Warning"
                                                        message:@"Permission was not granted for Contacts."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    }
        break;
    default:
        break;
 }
   }

Questions:
Answers:

Thanks to mahesh and wzbozon, the following code worked for me:

CFErrorRef * error = NULL;
addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
 {
     if (granted)
     {
         dispatch_async(dispatch_get_main_queue(), ^{
             CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
             CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

             for(int i = 0; i < numberOfPeople; i++){
                 ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );

                 NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
                 NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
                 NSLog(@"Name:%@ %@", firstName, lastName);

                 ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);

                 NSMutableArray *numbers = [NSMutableArray array];
                 for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
                     NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
                     [numbers addObject:phoneNumber];
                 }

                 NSMutableDictionary *contact = [NSMutableDictionary dictionary];
                 [contact setObject:name forKey:@"name"];
                 [contact setObject:numbers forKey:@"numbers"];

                 [all_contacts addObject:contact];
             }
         });
     }
 });

Questions:
Answers:

Swift version:

override func viewDidLoad() {
    super.viewDidLoad()

    var error: Unmanaged<CFErrorRef>?

    var addressBook: ABAddressBook = ABAddressBookCreateWithOptions(nil, &error).takeRetainedValue()


    if ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.NotDetermined {
        ABAddressBookRequestAccessWithCompletion(addressBook,  {

            (granted:Bool, error:CFErrorRef!) -> Void in

            self.populateFrom(addressBook: addressBook)

        })
    }
    else if ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.Authorized {

        self.populateFrom(addressBook: addressBook)

    }

}

func populateFrom(#addressBook:ABAddressBook){
    let allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue()
    let nPeople = ABAddressBookGetPersonCount(addressBook)
    for index in 0..<nPeople{
        let person: ABRecordRef = Unmanaged<ABRecordRef>.fromOpaque(COpaquePointer(CFArrayGetValueAtIndex(allPeople, index))).takeUnretainedValue()
        let firstName: String = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeUnretainedValue() as? String
        println("\(firstName.debugDescription)")


    }

}

Questions:
Answers:

Check out https://github.com/heardrwt/RHAddressBook (254 stars 01/2014).

Provides an ObjC wrapper for AddressBook with much simpler API.

Questions:
Answers:

This works for ios 7 and ios 8 , i hope its help you………….

NSMutableArray *result = [[NSMutableArray alloc] init];
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
__block BOOL accessGranted = NO;

if (ABAddressBookRequestAccessWithCompletion != NULL){
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);

    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        accessGranted = granted;
        dispatch_semaphore_signal(sema);
    });
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else{
    accessGranted = YES;
}
if (accessGranted){
    // If the app is authorized to access the first time then add the contact
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

    for (int i=0; i<numberOfPeople; i++){
        CFStringRef phone;
        ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
        CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
        CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
        NSString *userName = @"NoName";

        userName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
        userName = [userName stringByReplacingOccurrencesOfString:@"(null)" withString:@""];

        ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
        CFIndex phoneNumberCount = ABMultiValueGetCount( phoneNumbers );

        phone = nil;

        for ( CFIndex ind= 0; ind<phoneNumberCount; ind++ ){
            CFStringRef phoneNumberLabel = ABMultiValueCopyLabelAtIndex( phoneNumbers, ind);
            CFStringRef phoneNumberValue = ABMultiValueCopyValueAtIndex( phoneNumbers, ind);

            // converts "_$!<Work>!$_" to "work" and "_$!<Mobile>!$_" to "mobile"
            // Find the ones you want here
            if (phoneNumberLabel != nil){
                NSStringCompareOptions  compareOptions = NSCaseInsensitiveSearch;
                if(CFStringCompare(phoneNumberLabel, CFSTR("mobile"),compareOptions)){
                    phone = phoneNumberValue;
                }
                phone = phoneNumberValue;

                NSStringCompareOptions  compareOptionss = NSCaseInsensitiveSearch;
                if(!CFStringCompare(phone, CFSTR("1-800-MY-APPLE"),compareOptionss)){
                    continue;
                }
                NSMutableArray *theKeys = [NSMutableArray arrayWithObjects:@"name", @"small_name",@"phone", @"checked", nil];
                NSMutableArray *theObjects = [NSMutableArray arrayWithObjects:userName, [userName lowercaseString],phone, @"NO", nil];
                NSMutableDictionary *theDict = [NSMutableDictionary dictionaryWithObjects:theObjects forKeys:theKeys];
                if (![[functions formatNumber:(__bridge NSString *)(phone)] isEqualToString:[[NSUserDefaults standardUserDefaults]valueForKey:@"phoneNumber"]]){
                    [result addObject:theDict];
                }
            }
        }
    }
}
//sort array
NSSortDescriptor * descriptor = [[NSSortDescriptor alloc] initWithKey:@"small_name"
                                                            ascending:YES]; // 1
NSArray * sortedArray = [result sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];

Questions:
Answers:
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );

for ( int i = 0; i < nPeople; i++ )
{
    ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
    ...
}

Questions:
Answers:

This is complete demo to fetch all contacts with table view.

import UIKit
import ContactsUI
import AddressBook
import Contacts

class ShowContactsVC: UIViewController,CNContactPickerDelegate,UITableViewDelegate,UITableViewDataSource
{



@IBOutlet weak var tableView: UITableView!
let peoplePicker = CNContactPickerViewController()
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var contacts = [CNContact]()
var option : Int = 0
var userAccessGranted : Bool = false
var dataArray : NSMutableArray?




override func viewDidLoad()
{
    super.viewDidLoad()

    peoplePicker.delegate = self

    self.checkIfUserAccessGranted()

    self.tableView.delegate = self
    self.tableView.dataSource = self


    navigationController!.navigationBar.barTintColor = UIColor.grayColor()


              if(self.userAccessGranted)
      {
         self.tableView.hidden = false
        fetchContacts()

    }

}

func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    if dataArray == nil {
        return 0;
    }
    else{


    return dataArray!.count
}
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCellWithIdentifier("TableCell", forIndexPath: indexPath) as! ContactsTableViewCell



    let data = dataArray![indexPath.row] as! Data;
    cell.lblName.text = data.name
    cell.imgContact.image = data.image
    return cell
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
{
    cell.backgroundColor = UIColor.cyanColor()

}




func checkIfUserAccessGranted()
{
    appDelegate.requestForAccess { (accessGranted) -> Void in
        if accessGranted {
            self.userAccessGranted = true;
        }else{
            self.userAccessGranted = false;
        }
    }
}





func fetchContacts()
{

    dataArray = NSMutableArray()

    let toFetch = [CNContactGivenNameKey, CNContactImageDataKey, CNContactFamilyNameKey, CNContactImageDataAvailableKey]
    let request = CNContactFetchRequest(keysToFetch: toFetch)

    do{
        try appDelegate.contactStore.enumerateContactsWithFetchRequest(request) {
            contact, stop in
            print(contact.givenName)
            print(contact.familyName)
            print(contact.identifier)

            var userImage : UIImage;
            // See if we can get image data
            if let imageData = contact.imageData {
                //If so create the image
                userImage = UIImage(data: imageData)!
            }else{
                userImage = UIImage(named: "no_contact_image")!
            }

            let data = Data(name: contact.givenName, image: userImage)
            self.dataArray?.addObject(data)

        }
    } catch let err{
        print(err)

    }

    self.tableView.reloadData()

}

func contactPickerDidCancel(picker: CNContactPickerViewController)
{
    picker.dismissViewControllerAnimated(true, completion: nil)
    self.navigationController?.popToRootViewControllerAnimated(true)
}



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}



}




import UIKit

class Data {


    let name : String
    let image : UIImage

    init(name : String, image : UIImage) {
        self.image = image
        self.name = name
    }

}

Questions:
Answers:

if you want to sort as a alphabetical, you can use below code.

 CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);

CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(kCFAllocatorDefault,
                                                           CFArrayGetCount(allPeople),
                                                           allPeople);

CFArraySortValues(peopleMutable,
                  CFRangeMake(0, CFArrayGetCount(peopleMutable)),
                  (CFComparatorFunction) ABPersonComparePeopleByName,
                  kABPersonSortByFirstName);