DeviceContactsHandler.swift 3.4 KB

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