Подтвердить что ты не робот

Интерфейс контактов эквивалентен ABAddressBook.ABAddressBookRegisterExternalChangeCallback

Я переношу приложение из устаревшей структуры адресной книги в новую структуру контактов. Приложение использует ABAddressBookRegisterExternalChangeCallback, чтобы получать уведомление, когда другое приложение меняет контакт.

Я не могу найти эквивалентную функциональность в структуре контактов. В документации Apple говорится, что центр уведомлений по умолчанию с уведомлением CNContactStoreDidChangeNotification:

Уведомление отправляется, когда изменения происходят в другом CNContactStore.

Принимая советы Apple, мой код выглядит следующим образом:

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

Однако я нашел две проблемы с этим подходом:

  • Я получаю уведомление обо всех изменениях, в том числе в моем собственном приложении.
  • Уведомления являются ложными - я получаю много уведомлений за одно изменение.

Если я зарегистрирую отладочное описание уведомления, когда изменение было внесено в мое приложение, я получаю что-то вроде этого:

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

И если изменения сделаны извне:

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

Как вы можете видеть, ничего очевидного, чтобы отличить их.

Может ли кто-нибудь сказать мне, как получить такое же поведение из структуры контактов, как можно получить от ABAddressBookRegisterExternalChangeCallback?

4b9b3361

Ответ 1

Во-первых, я бы рекомендовал подавать ошибку в Apple об отсутствии способа идентифицировать внутренние и внешние изменения в API.

В качестве возможного обходного пути вы могли бы увидеть, если отмена регистрации наблюдателя перед внесением изменений и повторной регистрации сразу после этого гарантирует, что вы пропустите все свои уведомления об изменениях и все еще получите все внешние:

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)
    }
}