Manager.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import Contacts
  2. final class ContactManager {
  3. private let contactStore = CNContactStore()
  4. /// Checks if the app has access to the user's contacts.
  5. func requestAccess() async -> Bool {
  6. await withCheckedContinuation { continuation in
  7. contactStore.requestAccess(for: .contacts) { granted, _ in
  8. continuation.resume(returning: granted)
  9. }
  10. }
  11. }
  12. /// Creates a new contact in the Apple contact list.
  13. /// - Parameter name: The name of the contact.
  14. /// - Returns: The generated `identifier` of the contact, or `nil` if an error occurs.
  15. func createContact(name: String) async -> String? {
  16. do {
  17. let contact = CNMutableContact()
  18. contact.givenName = name
  19. let saveRequest = CNSaveRequest()
  20. saveRequest.add(contact, toContainerWithIdentifier: nil)
  21. try contactStore.execute(saveRequest)
  22. // Re-fetch the contact to retrieve its `identifier`.
  23. let predicate = CNContact.predicateForContacts(matchingName: name)
  24. let contacts = try contactStore.unifiedContacts(
  25. matching: predicate,
  26. keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor]
  27. )
  28. return contacts.first?.identifier // Return the `identifier`.
  29. } catch {
  30. print("Error creating contact: \(error)")
  31. return nil
  32. }
  33. }
  34. /// Deletes a contact from the Apple contact list using its `identifier`.
  35. /// - Parameter identifier: The unique identifier of the contact.
  36. /// - Returns: `true` if the contact was successfully deleted, `false` otherwise.
  37. func deleteContact(withIdentifier identifier: String) async -> Bool {
  38. do {
  39. // Attempt to find the contact using its identifier.
  40. let predicate = CNContact.predicateForContacts(withIdentifiers: [identifier])
  41. let contacts = try contactStore.unifiedContacts(
  42. matching: predicate,
  43. keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor]
  44. )
  45. guard let contact = contacts.first else {
  46. print("Contact with ID \(identifier) not found.")
  47. return false
  48. }
  49. // Contact found -> Delete it.
  50. let mutableContact = contact.mutableCopy() as! CNMutableContact
  51. let deleteRequest = CNSaveRequest()
  52. deleteRequest.delete(mutableContact)
  53. try contactStore.execute(deleteRequest)
  54. print("Contact successfully deleted: \(identifier)")
  55. return true
  56. } catch {
  57. print("Error deleting contact: \(error)")
  58. return false
  59. }
  60. }
  61. /// Updates an existing contact in the Apple contact list.
  62. /// - Parameters:
  63. /// - identifier: The unique identifier of the contact.
  64. /// - newName: The new name to assign to the contact.
  65. /// - Returns: `true` if the contact was successfully updated, `false` otherwise.
  66. func updateContact(withIdentifier identifier: String, newName: String) async -> Bool {
  67. do {
  68. // Search for the contact using its `identifier`.
  69. let predicate = CNContact.predicateForContacts(withIdentifiers: [identifier])
  70. let contacts = try contactStore.unifiedContacts(
  71. matching: predicate,
  72. keysToFetch: [
  73. CNContactIdentifierKey as CNKeyDescriptor,
  74. CNContactGivenNameKey as CNKeyDescriptor,
  75. CNContactFamilyNameKey as CNKeyDescriptor
  76. ]
  77. )
  78. guard let contact = contacts.first else {
  79. print("Contact with ID \(identifier) not found.")
  80. return false
  81. }
  82. // Update the contact.
  83. let mutableContact = contact.mutableCopy() as! CNMutableContact
  84. mutableContact.givenName = newName // Example: Update the given name.
  85. let updateRequest = CNSaveRequest()
  86. updateRequest.update(mutableContact)
  87. try contactStore.execute(updateRequest)
  88. print("Contact successfully updated: \(identifier)")
  89. return true
  90. } catch {
  91. print("Error updating contact: \(error)")
  92. return false
  93. }
  94. }
  95. }