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.
IOS 5 added iCloud and if your contacts are not turned ON from the iCloud settings, you won't be able to add, edit or delete contacts. The Fix: turn ON your iCloud contacts settings from Settings > iCloud and you should see your + sign on the corner back again.
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.
To present default contact controller
Step 1: Add ContactUi.framework into project and import
#import <Contacts/Contacts.h> #import <ContactsUI/ContactsUI.h>
Step2: Add this code
-(void)showAddContactController{ //Pass nil to show default contact adding screen CNContactViewController *addContactVC = [CNContactViewController viewControllerForNewContact:nil]; addContactVC.delegate=self; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addContactVC]; [viewController presentViewController:navController animated:NO completion:nil]; }
Step3:
For getting call back when pressing DONE or CANCEL, Add <CNContactViewControllerDelegate>
and implement the delegate method.
- (void)contactViewController:(CNContactViewController *)viewController didCompleteWithContact:(nullable CNContact *)contact{ //You will get the callback here }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With