ContactsChangeNotifier
Which contacts changed outside your iOS app? Better CNContactStoreDidChange notification: Get real changes, without the noise.
Why Oh Why
Sadly, the Contacts changes API is a mess:
- The 
CNContactStoreDidChangenotification is received for changes your own code did, not just outside your app.π€·  - It contains undocumented 
userInfofields.π  - To get the actual changes, you need to use an Objective-C API that is not even callable from Swift. 
π±  - That API is easy to get wrong, and requires maintaining opaque state, or receiving the complete changes history. 
𧨠 
Itβs the API that time forgot. 
ContactsChangeNotifier Features
- Only get notified for changes outside your app. 
π―  - Get the list of changes included in the notification. 
π  - Only get changes since last notification, not the full all-time history. 
β¨  - No Objective-C required. 
π₯  
Usage
- Get the user's Contacts access permission (see docs).
 - Keep a 
ContactsChangeNotifierinstance - it will observe all Contacts changes but post only those that from outside your app. - Observe 
ContactsChangeNotifier.didChangeNotificationnotification. - See change events in the notification's 
contactsChangeEvents. 
// 2. Keep a ContactsChangeNotifier instance
let contactsChangeNotifier = try! ContactsChangeNotifier(
    store: myCNContactStore,
    fetchRequest: .fetchRequest(additionalContactKeyDescriptors: myCNKeyDescriptors)
)
// 3. Observe ContactsChangeNotifier.didChangeNotification notification
let observation = NotificationCenter.default.addObserver(
    forName: ContactsChangeNotifier.didChangeNotification,
    object: nil,
    queue: nil
) { notification in
    // 4. See change events in the notification's contactsChangeEvents
    for event in notification.contactsChangeEvents ?? [] {
        switch event {
        case let addEvent as CNChangeHistoryAddContactEvent:
            print(addEvent.contact)
        case let updateEvent as CNChangeHistoryUpdateContactEvent:
            print(updateEvent.contact)
        case let deleteEvent as CNChangeHistoryDeleteContactEvent:
            print(deleteEvent.contactIdentifier)
        default:
            // group event
            break
        }
    }
}
Installation
CocoaPods:
pod 'ContactsChangeNotifier'
Swift Package Manager:
dependencies: [
    .package(url: "https://github.com/yonat/ContactsChangeNotifier", from: "1.0.1")
]