Contacts Framework Integration in iOS App
Apple renamed and rewrote the contacts API starting with iOS 9 — the old AddressBook framework is long deprecated, the current one is Contacts.framework. Despite this, projects still use ABAddressBook, which in iOS 18 no longer compiles without warnings and will disappear completely.
Permissions: what changed in iOS 18
iOS 18 introduced a new access type — Limited Access. Users can now choose specific contacts the app can read rather than granting access to the entire address book. CNAuthorizationStatus gained a new case: .limited.
If the app doesn't handle .limited — it silently gets an empty contact list for some iOS 18 users and developers don't understand why. Need to add NSContactsLimitedUsageDescription to Info.plist and explicitly handle this case: show UI with explanation, offer to expand access via CNContactStore.requestAccess.
Typical tasks and implementation
Fetching contacts with needed fields via CNContactFetchRequest:
let store = CNContactStore()
let keysToFetch: [CNKeyDescriptor] = [
CNContactGivenNameKey as CNKeyDescriptor,
CNContactFamilyNameKey as CNKeyDescriptor,
CNContactPhoneNumbersKey as CNKeyDescriptor,
CNContactEmailAddressesKey as CNKeyDescriptor,
CNContactThumbnailImageDataKey as CNKeyDescriptor
]
let request = CNContactFetchRequest(keysToFetch: keysToFetch)
request.sortOrder = .familyName
try store.enumerateContacts(with: request) { contact, stop in
// process per-contact, don't load all into memory at once
}
enumerateContacts is preferable to unifiedContacts(matching:keysToFetch:) with large address books: it doesn't load all contacts into memory simultaneously. On iPhone with 3000+ contacts, the second approach creates noticeable memory spike.
Adding a new contact with CNMutableContact and saving via CNSaveRequest — standard approach. When updating an existing contact, get its mutableCopy() — modifying original CNContact throws exception because it's immutable.
What's included in the work
- Setting up permissions for iOS 17 and iOS 18 (Limited Access)
- Fetching contacts with needed fields, sorting
- Searching by name, phone, email via
CNContactVCardSerializationor predicates - Creating and updating contacts
- Displaying system
CNContactPickerViewController - Handling duplicates through unification (
unifiedContact)
Timeline
1–3 days depending on operation scope. Basic read-only access with search — 1 day. Full CRUD with Limited Access handling and testing — up to 3 days. Cost calculated individually.







