DeviceContactsHandler.swift 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import Contacts
  2. import UIKit
  3. class DeviceContactsHandler {
  4. private let store = CNContactStore()
  5. weak var contactListDelegate: ContactListDelegate?
  6. private func makeContactString(contacts: [CNContact]) -> String {
  7. var contactString: String = ""
  8. for contact in contacts {
  9. let displayName: String = "\(contact.givenName) \(contact.familyName)"
  10. // cnContact can have multiple email addresses -> create contact for each email address
  11. for emailAddress in contact.emailAddresses {
  12. contactString += "\(displayName)\n\(emailAddress.value)\n"
  13. }
  14. }
  15. return contactString
  16. }
  17. private func addContactsToCore() {
  18. fetchContactsWithEmailFromDevice() { contacts in
  19. DispatchQueue.main.async {
  20. let contactString = self.makeContactString(contacts: contacts)
  21. dc_add_address_book(mailboxPointer, contactString)
  22. self.contactListDelegate?.deviceContactsImported()
  23. }
  24. }
  25. }
  26. private func fetchContactsWithEmailFromDevice(completionHandler: @escaping ([CNContact])->Void) {
  27. DispatchQueue.global(qos: .background).async {
  28. let keys = [CNContactFamilyNameKey, CNContactGivenNameKey, CNContactEmailAddressesKey]
  29. var fetchedContacts: [CNContact] = []
  30. var allContainers: [CNContainer] = []
  31. do {
  32. allContainers = try self.store.containers(matching: nil)
  33. } catch {
  34. return
  35. }
  36. for container in allContainers {
  37. let predicates = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
  38. let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
  39. request.mutableObjects = true
  40. request.unifyResults = true
  41. request.sortOrder = .userDefault
  42. request.predicate = predicates
  43. do {
  44. try self.store.enumerateContacts(with: request) { contact, _ in
  45. if !contact.emailAddresses.isEmpty {
  46. fetchedContacts.append(contact)
  47. } else {
  48. print(contact)
  49. }
  50. }
  51. } catch {
  52. print(error)
  53. }
  54. }
  55. return completionHandler(fetchedContacts)
  56. }
  57. }
  58. public func importDeviceContacts() {
  59. switch CNContactStore.authorizationStatus(for: .contacts) {
  60. case .authorized:
  61. addContactsToCore()
  62. contactListDelegate?.accessGranted()
  63. case .denied:
  64. contactListDelegate?.accessDenied()
  65. case .restricted, .notDetermined:
  66. store.requestAccess(for: .contacts) { [unowned self] granted, _ in
  67. if granted {
  68. DispatchQueue.main.async {
  69. self.addContactsToCore()
  70. self.contactListDelegate?.accessGranted()
  71. }
  72. } else {
  73. DispatchQueue.main.async {
  74. self.contactListDelegate?.accessDenied()
  75. }
  76. }
  77. }
  78. }
  79. }
  80. }