Skip to content

Instantly share code, notes, and snippets.

@anirudhamahale
Last active November 18, 2019 06:32
Show Gist options
  • Save anirudhamahale/f77460078700b178cb36ef0853d59cfe to your computer and use it in GitHub Desktop.
Save anirudhamahale/f77460078700b178cb36ef0853d59cfe to your computer and use it in GitHub Desktop.
Fetches contacts.
import Contacts
class PhoneContacts {
struct Contact {
let givenName: String
let middleName: String
let familyName: String
let phoneNumber: [String]
let email: [String]
}
static func readAll() -> [Contact]? {
let contactStore = CNContactStore()
// Get all the containers
var allContainers: [CNContainer] = []
do {
allContainers = try contactStore.containers(matching: nil)
} catch let error {
// Request Denied by user.
print("Error fetching containers due to \(error.localizedDescription)")
return nil
}
return getCNContacts(from: allContainers, contactStore: contactStore).map { contact -> Contact in
let givenName = contact.givenName
let middleName = contact.middleName
let familyName = contact.familyName
let email = getEmailAddress(from: contact.emailAddresses)
let phoneNumber = getPhoneNumber(from: contact.phoneNumbers)
return Contact(givenName: givenName, middleName: middleName, familyName: familyName, phoneNumber: phoneNumber, email: email)
}
}
private static func getCNContacts(from containers: [CNContainer], contactStore: CNContactStore) -> [CNContact] {
let keysToFetch = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactGivenNameKey,
CNContactMiddleNameKey,
CNContactFamilyNameKey,
CNContactPhoneNumbersKey,
CNContactEmailAddressesKey,
] as [Any]
var results: [CNContact] = []
// Iterate all containers and append their contacts to our results array
for container in containers {
let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
do {
let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
results.append(contentsOf: containerResults)
} catch {
print("Error fetching results for container")
}
}
results.sort { (contact0, contact1) -> Bool in
return contact0.givenName.lowercased() < contact1.givenName.lowercased()
}
return results
}
private static func getPhoneNumber(from numbers: [CNLabeledValue<CNPhoneNumber>]) -> [String] {
return numbers.compactMap { $0.value.stringValue }
}
private static func getEmailAddress(from address: [CNLabeledValue<NSString>]) -> [String] {
return address.compactMap { $0.value as String }
}
}
@anirudhamahale
Copy link
Author

Don't forget to add NSContactsUsageDescription to the Info.plist file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment