Exporting all contacts in one .vcf file using Contacts.Framework in Objective - C

2.2k views Asked by At

Using I AddressBook.framework I used to create Contacts.vcf from all contacts and save it in Documents Directory. Here is the code I used to use :

ABAddressBookRef addressBook1 = ABAddressBookCreate();
NSArray *arrayOfAllPeople = (__bridge_transfer NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook1);
long cnt = (unsigned long)[arrayOfAllPeople count];
if (cnt==0) {

    ABAddressBookRequestAccessWithCompletion(addressBook1, nil);

}

if(ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
    ABAddressBookRef addressBook2 = ABAddressBookCreate();


    CFArrayRef contacts = ABAddressBookCopyArrayOfAllPeople(addressBook2);
    CFDataRef vcards = (CFDataRef)ABPersonCreateVCardRepresentationWithPeople(contacts);


    NSString *vcardString = [[NSString alloc] initWithData:(__bridge NSData *)vcards encoding:NSUTF8StringEncoding];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *folderPath = [paths objectAtIndex:0];
    NSString *filePath = [folderPath stringByAppendingPathComponent:@"Contacts.vcf"];
    [vcardString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    CFRelease(addressBook2); }

How do I create a Contacts.vcf file having all device contacts using Contacts.framework and save it in documents directory ?

2

There are 2 answers

0
Dipankar Das On BEST ANSWER

You can use this method to get all the contacts in .vcf file. It return the same output that you get using AddressBook.framework.

- (void)getContacts {
    NSMutableArray *contactsArray=[[NSMutableArray alloc] init];
    CNContactStore *store = [[CNContactStore alloc] init];
    [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (!granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
            });
            return;
        }
        NSMutableArray *contacts = [NSMutableArray array];

        NSError *fetchError;

        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[[CNContactVCardSerialization descriptorForRequiredKeys], [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) {

            [contactsArray addObject:contact];
            // NSString *string = [formatter stringFromContact:contact];

            //NSLog(@"contact = %@", string);
        }

        //NSError *error;
        NSData *vcardString =[CNContactVCardSerialization dataWithContacts:contactsArray error:&error];

        NSString* vcardStr = [[NSString alloc] initWithData:vcardString encoding:NSUTF8StringEncoding];
        NSLog(@"vcardStr = %@",vcardStr);

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *folderPath = [paths objectAtIndex:0];
        NSString *filePath = [folderPath stringByAppendingPathComponent:@"Contacts.vcf"];
        [vcardStr writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }];
}
1
Mutawe On

From iOS 9+ version AddressBookUI.framework and Addressbook.framework becomes deprecated. Apple introduced ContactUI.framework and Contact.framework with enhancements over AddressBookUI.framework and Addressbook.framework. In this blog we will talk about how to use these two new frameworks and export VCard. Let’s start picking contact from phone contacts and access basic information of that person.

Step 1. Create new Xcode project name ContactDemo and import Contacts.framework and ContactsUI.framework as shown in picture.

Step 1

Step 2. In project add UIButton, UIImageView and 3 UILabels as shown in picture :

Step 2

Step 3. Create outlets of button action, imageview and labels in respective view controller as :

@property (weak, nonatomic) IBOutlet UIImageView *personImage;
@property (weak, nonatomic) IBOutlet UILabel *personName;
@property (weak, nonatomic) IBOutlet UILabel *emailId;
@property (weak, nonatomic) IBOutlet UILabel *phoneNo;

- (IBAction)selectAction:(id)sender;

Step 4. Add delegate CNContactPickerDelegate to viewController.

Step 5. Add delegate method :

- (void) contactPicker:(CNContactPickerViewController *)picker
didSelectContact:(CNContact *)contact {
[self getContactDetails:contact];
}

This delegate method will return contact in the form of CNContact object which will be further processed in local method

-(void)getContactDetails:(CNContact *)contactObject {

NSLog(@"NAME PREFIX :: %@",contactObject.namePrefix);
NSLog(@"NAME SUFFIX :: %@",contactObject.nameSuffix);
NSLog(@"FAMILY NAME :: %@",contactObject.familyName);
NSLog(@"GIVEN NAME :: %@",contactObject.givenName);
NSLog(@"MIDDLE NAME :: %@",contactObject.middleName);


NSString * fullName = [NSString stringWithFormat:@"%@ %@",contactObject.givenName,contactObject.familyName];
[self.personName setText:fullName];


if(contactObject.imageData) {
NSData * imageData = (NSData *)contactObject.imageData;
UIImage * contactImage = [[UIImage alloc] initWithData:imageData];
[self.personImage setImage:contactImage];
}

NSString * phone = @"";
NSString * userPHONE_NO = @"";
for(CNLabeledValue * phonelabel in contactObject.phoneNumbers) {
CNPhoneNumber * phoneNo = phonelabel.value;
phone = [phoneNo stringValue];
if (phone) {
userPHONE_NO = phone;
}}

NSString * email = @"";
NSString * userEMAIL_ID = @"";
for(CNLabeledValue * emaillabel in contactObject.emailAddresses) {
email = emaillabel.value;
if (email) {
userEMAIL_ID = email;
}}

NSLog(@"PHONE NO :: %@",userPHONE_NO);
NSLog(@"EMAIL ID :: %@",userEMAIL_ID);
[self.emailId setText:userEMAIL_ID];
[self.phoneNo setText:userPHONE_NO];
}

Step 6. Create CNContactPickerViewController class object and register its delegate in button IBAction method :

- (IBAction) selectAction:(id)sender {
CNContactPickerViewController *contactPicker = [CNContactPickerViewController new];
contactPicker.delegate = self;
[self presentViewController:contactPicker animated:YES completion:nil];
}

[self presentViewController:contactPicker animated:YES completion:nil]; will present view of contact list.

Step 7. Run project

A . Main View

Step 7

B. On Tapping “Select Contact” button CNContactPickerViewController will open as shown in picture :

Step 7B

C. Pick one contact and view will dismiss and you will get details of that contact as shown in picture :

Step 7C

Earlier we have write permission code to access contacts but now it implicitly grants permission for accessing contacts. With this framework we can also generate VCard(VCF) and share among other platforms. Here is the steps to create VCard.

Step 1. Pick contact from CNContactPickerViewController and you will get CNContact Object in delegate as mention above.

Step 2. Save contact in document directory. As data is stored in NSData form so to convert contact to NSData use CNContactVCardSerialization class that represents VCard in NSData format.

- (NSString *) saveContactToDocumentDirectory:(CNContact *)contact {

NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory,     NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString * VCardPath = [documentsDirectory stringByAppendingString:@"/VCard.vcf"];

NSArray *array = [[NSArray alloc] initWithObjects:contact, nil];

NSError *error;
NSData *data = [CNContactVCardSerialization dataWithContacts:array error:&error];
[data writeToFile:VCardPath atomically:YES];

return VCardPath;
}

CNContactVCardSerialization class method dataWithContacts:error: takes array of contact objects(CNContact class Object).

saveContactToDocumentDirectory method will return the file path of Vcard. With File path you can export contact anywhere you want.

Source: Contacts UI, Contacts Framework and create VCard(VCF) in Objective-C