Access the user's contacts and format and localize contact information.
- iOS 9.0+
- macOS 10.11+
- watchOS 2.0+
The Contacts framework provides Swift and Objective-C API to access the user’s contact information. Because most apps read contact information without making any changes, this framework is optimized for thread-safe, read-only usage.
Working with the User’s Contacts
This framework is available on all Apple platforms and replaces the Address Book framework in iOS and macOS.
The contact class (
CNContact) is a thread-safe, immutable value object of contact properties, such as the contact’s name, image, or phone numbers.
The contact class is like
NSDictionary in that it has a mutable subclass
CNMutable you can use to modify contact properties. For contact properties that can have multiple values, such as phone numbers or email addresses, an array of
CNLabeled objects is used. The labeled value class is a thread-safe, immutable tuple of labels and values. Labels describe each value to the user, allowing differentiation such as home and work phone numbers. The Contacts framework provides some predefined labels and you can create your own custom labels.
Formatting and Localization
The Contacts framework helps you format and localize contact information. For example, you can correctly format a contact name (using
CNContact) or format an international postal address (using
You can display localized object property names and predefined labels, based on the current locale setting of the device. Many objects defined in the Contacts framework, such as
CNContact, include the
localized method, which lets you get the localized version of a key name. In addition, the
CNLabeled class includes the
localized method, which lets you get the localized label for the predefined labels in the Contacts framework.
You can fetch contacts using the contact store (
CNContact), which represents the user's contacts database. The contact store encapsulates all I/O operations and is responsible for fetching and saving of contacts and groups. Because the contact store methods are synchronous, it is recommended that you use them on background threads. If needed, you can safely send immutable fetch results back to the main thread.
The Contacts framework provides several ways to constrain contacts returned from a fetch, including predefined predicates and the
CNContact provides predicates for filtering the contacts you want to fetch. For example, to fetch contacts that have the name “Appleseed”, use
predicate and pass in
Note that generic and compound predicates are not supported by the Contacts framework.
You can use
keys to limit the contact properties that are fetched. For example, if you want to fetch only the given name and the family name of a contact, you specify those contact keys in a
The Contacts framework can also perform operations on the fetched contacts, such as formatting contact names. Each operation requires a specific set of contact keys to correctly perform the operation. The keys are specified as key descriptor objects that must be included within the
keys array. For example, if you want to fetch the contact’s email addresses and also be able to format the contact’s name (using
CNContact), include both
CNContact and the key descriptor object returned by
descriptor in the
Users can grant or deny access to contact data on a per-app basis. Any call to
CNContact will block the app while the user is being asked to grant or deny access. Note that the user is prompted only the first time access is requested; any subsequent
CNContact calls use the existing permissions. To avoid having your app’s UI main thread block for this access, you can use either the asynchronous method
request or dispatch your
CNContact usage to a background thread.
A partial contact has only some of its property values fetched from a contact store. All fetched contact objects are partial contacts. If you try to access a property value that was not fetched, you get an exception. If you are unsure which keys were fetched in the contact, it is recommended that you check the availability of the property values before you access them. You can either use
is to check the availability of a single contact key, or
are to check multiple keys. If the desired keys are not available then refetch the contact with them.
Contacts in different accounts that represent the same person may be automatically linked together. Linked contacts are displayed in macOS and iOS apps as unified contacts. A unified contact is an in-memory, temporary view of the set of linked contacts that are merged into one contact.
By default the Contacts framework returns unified contacts. Each fetched unified contact (
CNContact) object has its own unique identifier that is different from any individual contact’s identifier in the set of linked contacts. A refetch of a unified contact should be done with its identifier.
The contact store (
CNContact) is also used to save changes to the Contacts framework objects. The
CNSave class enables save operations and allows batching of changes to multiple contacts and groups into a single operation. After all objects are added to the save request, it can be executed with a contact store as shown Listing 9 code listing below. Do not access the objects in the save request while the save is executing, because the objects may be modified.
Contacts Changed Notifications
After a save is successfully executed, the contact store posts a
CNContact notification to the default notification center. If you cache any Contacts framework objects you need to refetch those objects, either by their identifiers, or with the predicates that were used to originally fetch them, and then release the cached objects. Note that cached objects are stale, but not invalid.
Containers and Groups
A user may have contacts in their device’s local account or server accounts configured to sync contacts. Each account has at least one container of contacts. A contact can be in only one container.
A group is a set of contacts within a container. Not all accounts support groups and some accounts support subgroups. An iCloud account has only one container and may have many groups but no subgroups. On the other hand, an Exchange account does not support groups, but may have multiple containers representing Exchange folders.