8

I want to get contact details in an iPhone with information like First Name, Last Name, Phone Number, Phone Number Type, Email Address, Email Address Type etc..

Can anyone help me with that?

I want to make a .csv file out of the contact details in a particular iPhone. I want to fetch iPhone address book data.

Plague
  • 466
  • 5
  • 15
Vivek2012
  • 772
  • 1
  • 13
  • 25

4 Answers4

13

Following is the code to get all informations of iPhone contact book...

    -(void)collectContacts
    {
        NSMutableDictionary *myAddressBook = [[NSMutableDictionary alloc] init];
        ABAddressBookRef addressBook = ABAddressBookCreate();
        CFArrayRef people  = ABAddressBookCopyArrayOfAllPeople(addressBook);
        for(int i = 0;i<ABAddressBookGetPersonCount(addressBook);i++)
        {
            ABRecordRef ref = CFArrayGetValueAtIndex(people, i);

            // Get First name, Last name, Prefix, Suffix, Job title 
            NSString *firstName = (NSString *)ABRecordCopyValue(ref,kABPersonFirstNameProperty);
            NSString *lastName = (NSString *)ABRecordCopyValue(ref,kABPersonLastNameProperty);
            NSString *prefix = (NSString *)ABRecordCopyValue(ref,kABPersonPrefixProperty);
            NSString *suffix = (NSString *)ABRecordCopyValue(ref,kABPersonSuffixProperty);
            NSString *jobTitle = (NSString *)ABRecordCopyValue(ref,kABPersonJobTitleProperty);

            [myAddressBook setObject:firstName forKey:@"firstName"];
            [myAddressBook setObject:lastName forKey:@"lastName"];
            [myAddressBook setObject:prefix forKey:@"prefix"];
            [myAddressBook setObject:suffix forKey:@"suffix"];
            [myAddressBook setObject:jobTitle forKey:@"jobTitle"];

            NSMutableArray *arPhone = [[NSMutableArray alloc] init];
            ABMultiValueRef phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
            for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++)
            {       
                CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);   
                NSString *phoneLabel =(NSString*) ABAddressBookCopyLocalizedLabel (ABMultiValueCopyLabelAtIndex(phones, j));
                NSString *phoneNumber = (NSString *)phoneNumberRef; 
                NSMutableDictionary *temp = [[NSMutableDictionary alloc] init];
                [temp setObject:phoneNumber forKey:@"phoneNumber"];
                [temp setObject:phoneLabel forKey:@"phoneNumber"];
                [arPhone addObject:temp];
                [temp release];
            }
            [myAddressBook setObject:arPhone forKey:@"Phone"];
            [arPhone release];            

            CFStringRef address;
            CFStringRef label;
            ABMutableMultiValueRef multi = ABRecordCopyValue(ref, kABPersonAddressProperty);    
            for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) 
            {           
                label = ABMultiValueCopyLabelAtIndex(multi, i);
                CFStringRef readableLabel = ABAddressBookCopyLocalizedLabel(label);             
                address = ABMultiValueCopyValueAtIndex(multi, i);   
                CFRelease(address);
                CFRelease(label);
            } 

            ABMultiValueRef emails = ABRecordCopyValue(ref, kABPersonEmailProperty);
            NSMutableArray *arEmail = [[NSMutableArray alloc] init];
            for(CFIndex idx = 0; idx < ABMultiValueGetCount(emails); idx++)
            {
                CFStringRef emailRef = ABMultiValueCopyValueAtIndex(emails, idx);
                NSString *strLbl = (NSString*) ABAddressBookCopyLocalizedLabel (ABMultiValueCopyLabelAtIndex (emails, idx));
                NSString *strEmail_old = (NSString*)emailRef;
                NSMutableDictionary *temp = [[NSMutableDictionary alloc] init];
                [temp setObject:strEmail_old forKey:@"strEmail_old"];
                [temp setObject:strLbl forKey:@"strLbl"];
                [arEmail addObject:temp];
                [temp release];
            }
            [myAddressBook setObject:arEmail forKey:@"Email"];
            [arEmail release];
        }
        [self createCSV:myAddressBook];
    }

    -(void) createCSV :(NSMutableDictionary*)arAddressData
    {   
        NSMutableString *stringToWrite = [[NSMutableString alloc] init];
        [stringToWrite appendString:[NSString stringWithFormat:@"%@,",[arAddressData valueForKey:@"firstName"]]];
        [stringToWrite appendString:[NSString stringWithFormat:@"%@,",[arAddressData valueForKey:@"lastName"]]];
        [stringToWrite appendString:[NSString stringWithFormat:@"%@,",[arAddressData valueForKey:@"jobTitle"]]];
        //[stringToWrite appendString:@"fname, lname, title, company, phonetype1, value1,phonetype2,value,phonetype3,value3phonetype4,value4,phonetype5,value5,phonetype6,value6,phonetype7,value7,phonetype8,value8,phonetype9,value9,phonetype10,value10,email1type,email1value,email2type,email2value,email3type,email3‌​value,email4type,email4value,email5type,email5value,website1,webs‌​ite2,website3"]; 
        NSMutableArray *arPhone = (NSMutableArray*) [arAddressData valueForKey:@"Phone"];
        for(int i = 0 ;i<[arPhone count];i++)
        {
            NSMutableDictionary *temp = (NSMutableDictionary*) [arPhone objectAtIndex:i];
            [stringToWrite appendString:[NSString stringWithFormat:@"%@,",[temp valueForKey:@"phoneNumber"]]];
            [stringToWrite appendString:[NSString stringWithFormat:@"%@,",[temp valueForKey:@"phoneNumber"]]];
            [temp release];
        }
        NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
        NSString *documentDirectory=[paths objectAtIndex:0];
        NSString *strBackupFileLocation = [NSString stringWithFormat:@"%@/%@", documentDirectory,@"ContactList.csv"];
        [stringToWrite writeToFile:strBackupFileLocation atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
alloc_iNit
  • 5,173
  • 2
  • 26
  • 54
  • now can u tell me how to build CSV file from this function while i click on button ..! need it urgent ..Thanks a lot . – Vivek2012 Aug 19 '11 at 10:42
  • There are many tutorial for the same and even many solutions in stack overflow itself too. Here is one of the link for the solution...http://stackoverflow.com/questions/1159576/how-to-export-data-to-a-csv-file-with-iphone-sdk-3-0 – alloc_iNit Aug 19 '11 at 11:11
  • Hey Still m not getting that .CSV file in my project .. can u plz tell me i need to make .csv file before or while i run my project that will generate automatically ?? and ya from above link i found array undeclared . wht should i do for that. ? reply as soon as possible ..Thanks – Vivek2012 Aug 23 '11 at 07:45
  • NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString* savePath = [paths objectAtIndex:0]; savePath = [savePath stringByAppendingPathComponent:@"components.csv"]; [[ContactsText compoentnsJoinedByString:@","] writeToFile:savePath atomically:YES encoding:NSUTF8StringEncoding error:NULL]; //[[ContactsText componentsJoinedByString:@","] writeToFile:@"components.csv" atomically:YES encoding:NSUTF8StringEncoding error:NULL]; NSLog(@" Data in the .CSV file = %@%",ContactsText); – Vivek2012 Aug 23 '11 at 10:24
  • by that i am not getting velue in my .csv file ... and also i want to display it in format like :initWithObjects:@"fname", @"lname", @"title", @"company",@"phonetype1", @"value1", @"phonetype2", @"value2", @"phonetype3", @"value3", @"phonetype4", @"value4", @"phonetype5", @"value5", @"phonetype6", @"value6", @"phonetype7", @"value7", @"phonetype8", @"value8", @"phonetype9", @"value9",@"phonetype10",@"value10", @"email1type",@"email1value",@"email2type",@"email2value",@"email3type",@"email3value",@"email4type",@"email4value",@"email5type",@"email5value","website1","website2","website3", nil]; – Vivek2012 Aug 23 '11 at 10:25
  • I have modified the existing code along with the sample code of .csv creation, check it as I haven't check with device. – alloc_iNit Aug 23 '11 at 13:10
  • 1
    Still not working ..This time i got the error in function collectContacts that "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: prefix)'" ..can u help me in that .... while i click on button i got this error.. – Vivek2012 Aug 26 '11 at 07:40
  • Please let me know the exact line of the method collectContacts. – alloc_iNit Aug 26 '11 at 08:54
  • The exception is trying to let you know that the value going to set in NSMUtableDictionary is NULL. So set condition to avoid null values to be stored in dictionary. – alloc_iNit Aug 26 '11 at 09:10
  • Finally done it ..but i didnt get ant data in that ...can u plz do something for that .. I got every data by consol but not getting in that .csv file .... – Vivek2012 Aug 26 '11 at 09:39
  • I have already given the sample code for CSV creation to give you the exact idea. I don't think after that you have to make much efforts. Just try it out. – alloc_iNit Aug 26 '11 at 09:43
  • Upload your project in github and send me the link. I have to go through your code. – alloc_iNit Aug 31 '11 at 04:18
  • Look m doing the same thing which u have told me ..but still i cant find my data in my .csv file ..can u give me your mail id so i can sent u that my .m and .h file .. and Go throught it .. also get problem in upload.. – Vivek2012 Aug 31 '11 at 05:17
  • And by that [myAddressBook setObject:firstName forKey:@"firstName"]; I get null value becoz of this it get crash .. Wht i need to do ...and still data has not come in my .csv file ..need your help urgent ... – Vivek2012 Aug 31 '11 at 07:33
  • Before setting the fileName to the myAddressBook, check for the null value like this, fileName = (fileName != nil) ? fileName : @""; [myAddressBook setObject:firstName forKey:@"firstName"]; and then set to the dictionary. – alloc_iNit Aug 31 '11 at 08:10
  • Still i am not able to get data in my .csv file ..it still comes blank ..can u tell me wht i need to write to call this function -(void) createCSV :(NSMutableDictionary*)arAddressData on button click event ... – Vivek2012 Aug 31 '11 at 08:36
  • As I have already given in my sample code, **self createCSV:myAddressBook];** will call and execute the method. – alloc_iNit Aug 31 '11 at 08:44
  • but still it shows myAdressbook is not declare .. i want to create it on button click which is in another function and m using this function on that button click event .. so now tell me wht i need to do .. – Vivek2012 Aug 31 '11 at 08:47
  • hey how to get recordID from above function ?? – Vivek2012 Sep 03 '11 at 08:03
  • and m still not getting data in my .csv file ..only first line comes other data which i can see by NSLog i am not able to write it in .csv file ..need it urgent .. – Vivek2012 Sep 03 '11 at 08:04
  • ABRecordID id_ = ABRecordGetRecordID(ref); – alloc_iNit Sep 03 '11 at 08:33
  • 3
    This code is buggy and doesn't work - have you tested this at all? One error is that myAddressBook is defined outside the loop, its values are set inside the loop - therefore each new contact is overwriting all the values for the previous contact. – n13 Feb 01 '12 at 07:50
  • @n13 Thanks for found out a minor bug. I have updated sample code accordingly. – alloc_iNit Jun 20 '12 at 04:48
  • Would you need to call CFRelease() on all those NSStrings received from ABRecordCopyValue()? – James Kuang Sep 27 '13 at 22:01
  • how to import this exported file as iPhone contacts? @alloc_iNit can you give me the hint?, I have already exported csv file, I have to import back as iphone contacts. – Ashish Kakkad Jun 23 '14 at 10:01
  • @AshishKakkad - Do you want to convert CSV to vcard? – alloc_iNit Jun 30 '14 at 11:17
  • @alloc_iNit yes, because we can import vCard easily – Ashish Kakkad Jun 30 '14 at 11:19
9

I used iApple's code above as a starting point and created a working version from it - this one just collects all address book entries in an array. As mentioned above the original iApple doesn't work, there's a few bugs in it. This one works, and was tested.

Note: This doesn't return any contacts that don't have a name set - you can remove that for your own code, I just did it because I only need contacts with names set, and NSMutableDictionary doesn't like nil entries (crashes).

In my own address book I have a few entries that are just an email - I am not sure how they got there, but it's certainly possible to have address book entries without a name. Keep that in mind when iterating over an address book.

I am using the full name as per Apple's recommendations - ABRecordCopyCompositeName returns a composite of first and last name in the order specified by the user.

Finally, I made this a static method and put it in a helper class.

This is for use with ARC!

// returns an array of dictionaries
// each dictionary has values: fullName, phoneNumbers, emails
// fullName is a string
// phoneNumbers is an array of strings
// emails is an array of strings
+ (NSArray *)collectAddressBookContacts {
    NSMutableArray *allContacts = [[NSMutableArray alloc] init];
    ABAddressBookRef addressBook = ABAddressBookCreate();
    CFArrayRef people  = ABAddressBookCopyArrayOfAllPeople(addressBook);
    for(int i = 0;i<ABAddressBookGetPersonCount(addressBook);i++)
    {
        NSMutableDictionary *aPersonDict = [[NSMutableDictionary alloc] init];
        ABRecordRef ref = CFArrayGetValueAtIndex(people, i);
        NSString *fullName = (__bridge NSString *) ABRecordCopyCompositeName(ref);
        if (fullName) {
            [aPersonDict setObject:fullName forKey:@"fullName"];

            // collect phone numbers
            NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
            ABMultiValueRef phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
            for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++) {
                NSString *phoneNumber = (__bridge NSString *) ABMultiValueCopyValueAtIndex(phones, j);
                [phoneNumbers addObject:phoneNumber];
            }
            [aPersonDict setObject:phoneNumbers forKey:@"phoneNumbers"];

            // collect emails - key "emails" will contain an array of email addresses
            ABMultiValueRef emails = ABRecordCopyValue(ref, kABPersonEmailProperty);
            NSMutableArray *emailAddresses = [[NSMutableArray alloc] init];
            for(CFIndex idx = 0; idx < ABMultiValueGetCount(emails); idx++) {
                NSString *email = (__bridge NSString *)ABMultiValueCopyValueAtIndex(emails, idx);
                [emailAddresses addObject:email];
            }
            [aPersonDict setObject:emailAddresses forKey:@"emails"];
            // if you want to collect any other info that's stored in the address book, it follows the same pattern.
            // you just need the right kABPerson.... property.

            [allContacts addObject:aPersonDict];
        } else {
            // Note: I have a few entries in my phone that don't have a name set
            // Example one could have just an email address in their address book.
        }
    }
    return allContacts;
}
n13
  • 6,843
  • 53
  • 40
2

First you will need to use the address book framework so this must be added to your Xcode project.

Next you will need to break the task down into a couple steps.

1) Get the people inside the address book

2) Create your .csv file. I'm assuming you know something about CSV file formatting using characters to separate fields and when to add return characters so you have a properly formatted file. This is probably left for another question thread if you need help with this.

3) Save your .csv file somewhere

1) To get an array of all people in the address book you would do something like the following. The reference documentation for ABAddressBook is here. It should be very helpful in helping you access the data.

ABAddressBook *sharedBook = [ABAddressBook sharedAddressBook];
NSArray *peopleList = [sharedBook people];

2) You will have to iterate through each of the people and build your overall csv data. Usually you would manually create the csv data in an NSString and then convert it to NSData and save the NSData to a file. This is not ideal if you are dealing with a really large set of data. If this is the case then you would probably want some code to write your csv data to the file in chunks so you can free memory as you go. For simplicity sake my code just shows you creating the full file then saving the whole works.

NSString *csvString = @"";
for(ABPerson *aPerson in peopleList) {
  //Do something here to write each property you want to the CSV file.
  csvString = [csvString stringByAppendingFormat:@"'%@'," 
                                    [aPerson valueForProperty:kABFirstNameProperty]];
}

NSData *csvData = [csvString dataUsingEncoding:NSUTF8StringEncoding];

3) Write you file to somewhere

//This is an example of writing your csv data to a file that will be saved in the application's sand box directory. 
//This file could be extracted using iTunes file sharing.

//Get the proper path to save the file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:@"my_file.csv"];

 //Actually write the data
 BOOL isSuccessful = [csvData writeToFile:fullPath atomically:NO];
 if(isSuccessful) {
     //Do something if the file was written
  } else {
    //Do something if there was an error writing the file
  }
Hazmit
  • 165
  • 6
  • Sory but not working ..it shows ABPerson ,ABAddressBook,fullPath undeclare .. how and where to declare those things ? – Vivek2012 Aug 19 '11 at 09:30
  • 1
    You probably haven't added the AddressBook framework to your project. You will need to Click on your project in the file browser on the left -> Select Build Phases from the tabs at the top -> Expand the "Link Binary With Libraries" section and click the plus. Search for "AddressBook.framework" and make sure it is added. From here you will likely need to #import into your project to include the proper headers for the classes you are trying to use. – Hazmit Aug 19 '11 at 09:40
  • nope i have use that .. can u do one thing i have use that above function and i am able to get value of contacts from my iPhone .. last thing i need is only that want to create csv file from above function .can u help me in that .?? – Vivek2012 Aug 19 '11 at 10:51
0

See Adress Book API particulary Importing and Exporting Person and Group Records

chack also the Address Book Test example in this blog

Mouna Cheikhna
  • 38,870
  • 10
  • 48
  • 69