iOS - add contact into Contacts?

contacts, email, ios, iphone, uibutton

Solution

If doing this in iOS 9 or later, you should 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.

Then, when you then want to programmatically add the contact, then you can do something like:

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) {
    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;
    }

    // create contact

    CNMutableContact *contact = [[CNMutableContact alloc] init];
    contact.familyName = @"Doe";
    contact.givenName = @"John";

    CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:[CNPhoneNumber phoneNumberWithStringValue:@"312-555-1212"]];
    contact.phoneNumbers = @[homePhone];

    CNSaveRequest *request = [[CNSaveRequest alloc] init];
    [request addContact:contact toContainerWithIdentifier:nil];

    // save it

    NSError *saveError;
    if (![store executeSaveRequest:request error:&saveError]) {
        NSLog(@"error = %@", saveError);
    }
}];

Or, even better, if you want to add the contact using the `ContactUI` framework (giving the user visual confirmation of the contact and let them tailor it as they see fit), you can import both frameworks:

@import Contacts;
@import ContactsUI;

And then:

CNContactStore *store = [[CNContactStore alloc] init];

// create contact

CNMutableContact *contact = [[CNMutableContact alloc] init];
contact.familyName = @"Smith";
contact.givenName = @"Jane";

CNLabeledValue *homePhone = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:[CNPhoneNumber phoneNumberWithStringValue:@"301-555-1212"]];
contact.phoneNumbers = @[homePhone];

CNContactViewController *controller = [CNContactViewController viewControllerForUnknownContact:contact];
controller.contactStore = store;
controller.delegate = self;

[self.navigationController pushViewController:controller animated:TRUE];

My original answer, using the `AddressBook` and `AddressBookUI` frameworks for iOS versions before 9, is below. But if only supporting iOS 9 and later, use the `Contacts` and `ContactsUI` frameworks as outlined above.

--

If you want to add a contact to the user's address book, you use `AddressBook.Framework` to create a contact, and then you use the `AddressBookUI.Framework` to present the user interface to allow the user to add it to their personal address book using `ABUnknownPersonViewController`. Thus, you can:

Add `AddressBook.Framework` and `AddressBookUI.Framework` to your list under Link Binary With Libraries;

Import the .h files:

#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>

Write the code to create a contact, e.g.:

// create person record

ABRecordRef person = ABPersonCreate();

// set name and other string values

ABRecordSetValue(person, kABPersonOrganizationProperty, (__bridge CFStringRef) venueName, NULL);

if (venueUrl) {
    ABMutableMultiValueRef urlMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    ABMultiValueAddValueAndLabel(urlMultiValue, (__bridge CFStringRef) venueUrl, kABPersonHomePageLabel, NULL);
    ABRecordSetValue(person, kABPersonURLProperty, urlMultiValue, nil);
    CFRelease(urlMultiValue);
}

if (venueEmail) {
    ABMutableMultiValueRef emailMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    ABMultiValueAddValueAndLabel(emailMultiValue, (__bridge CFStringRef) venueEmail, kABWorkLabel, NULL);
    ABRecordSetValue(person, kABPersonEmailProperty, emailMultiValue, nil);
    CFRelease(emailMultiValue);
}

if (venuePhone) {
    ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    NSArray *venuePhoneNumbers = [venuePhone componentsSeparatedByString:@" or "];
    for (NSString *venuePhoneNumberString in venuePhoneNumbers)
        ABMultiValueAddValueAndLabel(phoneNumberMultiValue, (__bridge CFStringRef) venuePhoneNumberString, kABPersonPhoneMainLabel, NULL);
    ABRecordSetValue(person, kABPersonPhoneProperty, phoneNumberMultiValue, nil);
    CFRelease(phoneNumberMultiValue);
}

// add address

ABMutableMultiValueRef multiAddress = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
NSMutableDictionary *addressDictionary = [[NSMutableDictionary alloc] init];

if (venueAddress1) {
    if (venueAddress2)
        addressDictionary[(NSString *) kABPersonAddressStreetKey] = [NSString stringWithFormat:@"%@\n%@", venueAddress1, venueAddress2];
    else
        addressDictionary[(NSString *) kABPersonAddressStreetKey] = venueAddress1;
}
if (venueCity)
    addressDictionary[(NSString *)kABPersonAddressCityKey] = venueCity;
if (venueState)
    addressDictionary[(NSString *)kABPersonAddressStateKey] = venueState;
if (venueZip)
    addressDictionary[(NSString *)kABPersonAddressZIPKey] = venueZip;
if (venueCountry)
    addressDictionary[(NSString *)kABPersonAddressCountryKey] = venueCountry;

ABMultiValueAddValueAndLabel(multiAddress, (__bridge CFDictionaryRef) addressDictionary, kABWorkLabel, NULL);
ABRecordSetValue(person, kABPersonAddressProperty, multiAddress, NULL);
CFRelease(multiAddress);

// let's show view controller

ABUnknownPersonViewController *controller = [[ABUnknownPersonViewController alloc] init];

controller.displayedPerson = person;
controller.allowsAddingToAddressBook = YES;

// current view must have a navigation controller

[self.navigationController pushViewController:controller animated:YES];

CFRelease(person);

See the ABUnknownPersonViewController Class Reference or the Prompting the User to Create a New Person Record from Existing Data section of the Address Book Programming Guide.

Problem

Heyo! Is there a way how when a user taps a button it can add or update a contact into the actual Apple Contacts Book? Some festivals have email responses include a "name card" that the receiver can download and find in their contact book.

Original source