ios swift abaddressbook cncontact cncontactstore

ios - Marco de contacto equivalente a ABAddressBook.ABAddressBookRegisterExternalChangeCallback



swift cncontact (1)

Estoy migrando una aplicación del marco de la libreta de direcciones en desuso al nuevo marco de contactos. La aplicación utiliza ABAddressBookRegisterExternalChangeCallback para ser notificado cuando otra aplicación cambie un contacto.

No puedo encontrar una funcionalidad equivalente en el Marco de contactos. La documentación de Apple dice que se debe usar el centro de notificaciones predeterminado con la notificación CNContactStoreDidChangeNotification :

La notificación publicada cuando se producen cambios en otro CNContactStore .

Siguiendo el consejo de Apple, mi código se ve así:

NSNotificationCenter.defaultCenter().addObserver( self, selector: "contactsChanged:", name: CNContactStoreDidChangeNotification, object: nil)

Sin embargo, he encontrado dos problemas con este enfoque:

  1. Estoy notificado de todos los cambios, incluidos los realizados por mi propia aplicación.
  2. Las notificaciones son espurias: recibo muchas notificaciones por un solo cambio.

Si registro la descripción de depuración de la notificación cuando se realizó el cambio dentro de mi aplicación, obtengo algo como esto:

NSConcreteNotification 0x7d3370e0 {name = CNContactStoreDidChangeNotification; userInfo = { CNNotificationOriginationExternally = 1; CNNotificationSourcesKey = ( ); }}

Y si los cambios se realizan externamente:

NSConcreteNotification 0x7bf7a690 {name = CNContactStoreDidChangeNotification; userInfo = { CNNotificationOriginationExternally = 1; CNNotificationSourcesKey = ( ); }}

Como puedes ver, nada obvio con lo que distinguirlos.

¿Alguien puede decirme cómo obtener el mismo comportamiento en el marco de contactos que uno puede obtener de ABAddressBookRegisterExternalChangeCallback ?


Primero, recomendaría presentar un error a Apple sobre la falta de una forma de identificar los cambios internos frente a los externos en la API.

Como una posible solución alternativa, puede ver si anular el registro de su observador antes de realizar un cambio y volver a registrarse inmediatamente después, se asegura de que no reciba todas las notificaciones de cambios y aún obtenga todas las notificaciones externas:

class ContactsThingy { var observer: NSObjectProtocol? let contacts = CNContactStore() func contactStoreDidChange(notification: NSNotification) { NSLog("%@", notification) } func registerObserver() { let center = NSNotificationCenter.defaultCenter() observer = center.addObserverForName(CNContactStoreDidChangeNotification, object: nil, queue: NSOperationQueue.currentQueue(), usingBlock: contactStoreDidChange) } func unregisterObserver() { guard let myObserver = observer else { return } let center = NSNotificationCenter.defaultCenter() center.removeObserver(myObserver) } func changeContacts(request: CNSaveRequest) { unregisterObserver() // stop watching for changes defer { registerObserver() } // start watching again after this change even if error try! contacts.executeSaveRequest(request) } }