Contacts Framework Vs AddressBook Swift 3.0

Contacts Framework

Contacts Framework came up  with iOS 9.0 . This framework provide Swift and Objective-C API to access the user’s contact information.

AddressBook Framework

AddressBook Framework was used in iOS 8 and earlier for access user’s contact information .

Through this blog you will get to understand working with Contacts and AddressBook Framework.  So before accessing the contact you have to take permission from user to access contact.

Permissions:

There are four type of permission states:

  1. Not determined:  When user installs the app and open for the first time.
  2. Denied: When user denied to access contact.
  3. Restricted:  This state can not be handle by user. This might be another reason to be restricted.
  4. Authorized:  When user allows to access contact.

Ask permission from user to access contact:

Contacts Framework:

In Contact Framework CNContactStore provides ways to execute fetch and save requests. authorizationStatus(for:)  returns the current authorization status to access the contact data. requestAccess(for:completionHandler:) requests access to user’s contacts.  ContactAccessError  is a custom error.

 

AddressBook Framework:

In AdressBook  ABAddressBookGetAuthorizationStatus() return current authorization status. if you will open the application first time, then the auterization status will be notDetermined. So in this case you have to request to access contact. In AddressBook Framework first you have to get the reference of AddressBook to request for access contacts.

ABAddressBookCreateWithOptions(_ options:, _ error: )  creates a new address book object (reference) with data from the Address Book database. This object is unmanaged( ie memory management is not controlled by the Swift runtime system). 

takeRetainedValue() get the value of an unmanaged reference as a managed reference (ie you want ARC to take care of releasing the object when you’re done).

ABAddressBookRequestAccessWithCompletion(_ addressBook: , _ completion: ) requests access to user’s contacts.

Note: One more thing you will have to do in your project to access user’s contact is:-     define Privacy – Contacts Usage Description key in info.plist file with description.

When you run the app for the first time and try to save, fetch or update contact, you should see the following alert.


What happens if the user doesn’t allow access?

If  user don’t allow to access contact, in this case  your app will stuck forever. So in case of denied you can so an alert  to user to allows access contact.

This will send the user to the Settings app, right to the page with your app’s permissions.

Save New Contacts

Contacts Framework:

Here I have created an object of model class ContactDetail which holds the detail of new contact like first name, last name, contact number, email etc.

The below function is for creating the new contact.  First you have  to create a CNMutableContact object and assign the givenName, familyName etc which you want to save.  For contact properties that can have multiple values, such as phone numbers or email addresses, an array of CNLabeledValue objects is used.  Here CNPhoneNumber class  returns a new phone number object initialized with the specified phone number string.

Note: Here CNContactViewController(for: contact) is used to show saved contact . This class   is of ContactsUI Framework. So you have to import ContactsUI framework.  The CNContactViewController  class implements the view to display a contact. CNContactViewController can display a new contact, unknown contact, or existing contact.

 

Note: To proceed any operation on contact like save, fetch, update or delete,  first you have to check permission by using checkPermission() method (discussed above). if access to contact is allowed then the process will proceed further otherwise catch block will execute and an alert will show to allow access contact (showPermissionAlert() discussed above).

To save contact create CNSaveRequest  object and call its  addContact(_:toContainerWithIdentifier:)  method to tell the Contacts framework that you want to create a new contact. By passing nil as the identifier, the new contact will be saved in the default contacts group.

AddressBook:

The call to ABPersonCreate() creates a reference to a new Address Book record. Once you have that, you can call ABRecordSetValue() and pass it the record, the field to change, and the value. Since one contact can have multiple phone numbers (home, mobile, etc.) and emails, you have to use ABMutableMultiValue  reference, which supports multiple values.  ABMultiValueAndLabel adds a value and its corresponding label to a multivalue property (ie phoneNumbers). The label kABPersonPhoneMainLabel says that this is the contact’s primary number. You can add another label as your requirements. The same step will be follow to create email. ABAddressBookAddRecord()  adds a record to addressBookRef.

Now contact is only added to reference of Address Book. It is not saved in Address Book database. To save in Address Book implement saveContact().  ABAddressBookHasUnsavedChanges() indicates whether an address book has changes that have not been saved to the Address Book database.  ABAddressBookSave() save the changes in Address Book.

Note: Here personViewcontroller is used to display saved contact which is the part of  AddressBookUI. So you have to import it .

Fetch Contacts

Contacts Framework:

 

 

As discussed earlier you can fetch contacts using the contact CNContactStore(), which represents the user’s contacts database. You can add some predicate(any string or character) to fetch contacts. CNContact provides predicates for filtering the contacts you want to fetch .

You can use keysToFetch to limit the contact properties that are fetched. For example if you want to fetch only name , phone number and email address then pass these  key in keyToFetch.

The Contacts framework can also perform operations on the fetched contacts, such as formatting contact names. Here in code there is a key  CNContactFormatter.descriptorForRequiredKeys(for: .fullName) in keyToFetch array. This will format the name of contact. For example if fetched contact givenName = “Jhon” and familyName = “Rich” then CNContactFormatter format the fullName = “Jhon Rich”.

unifiedContactsMatchingPredicate(_:keysToFetch:) method of CNContactStore unified the result. That is if a user has multiple contacts that relate to the same person, they can link these together in the Contacts app. When your app tries to access this user’s contacts, rather than returning multiple CNContact instances, the Contacts framework unifies these together into one object so your app can display information correctly and interpret it easily.

AddressBook Framework:

In AddressBook framework  you can fetch contact by reference of AddressBook .As discussed earlier  ABAddressBookCreate give the reference ok AddressBook. Tp fetch all record yo can call  ABAddressBookCopyArrayOfAllPeople() methodIn AddressBook framework there is no any method to apply predicate . so you have to write the code to compare to find particular result.

Delete Contact

Contacts Framework:

Note: In contacts Framework there is delete(_ contact:) method to delete contact. the contact fetched is of CNContact type . So you have to convert it into CNMutableContact then pass in delete() method.

AddressBook Framework:

In AddressBook Framework call  ABAddressBookRemoveRecord(_ addressBook: , _ record: , _ error:) will delete record from addressbookRef but not from the AddressBook database. So after remove call the ABAddressBookSave(_ addressBook:, _ error: ) method to reflect changes in database.

Update Contact

Contacts Framework:

Similar to delete there is update(_ contact:)  method in contact Framework to update existing contact.

AddressBook Framework:

To update contact in AddressBook you can use the method ABAddressBookHasUnsavedChanges() of ABAddressBook. If it returns true then call save method to save changes. (Similar to Add new contact).

Leave a Reply