23

我正在将应用程序从已弃用的通讯簿框架迁移到新的联系人框架。该应用程序ABAddressBookRegisterExternalChangeCallback用于在另一个应用程序更改联系人时得到通知。

我无法在联系人框架中找到等效功能。Apple 文档说要使用默认通知中心CNContactStoreDidChangeNotification通知

当另一个CNContactStore.

听从 Apple 的建议,我的代码如下所示:

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

但是,我发现这种方法存在两个问题:

  1. 我会收到所有更改的通知,包括我自己的应用程序所做的更改。
  2. 通知是虚假的 - 我收到很多通知,只是一次更改。

如果我在我的应用程序中进行更改时记录通知的调试描述,我会得到如下信息:

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

如果更改是在外部进行的:

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

如您所见,没有什么明显的区别可以用来区分它们。

谁能告诉我如何从联系人框架中获得与从联系人框架中获得的相同行为ABAddressBookRegisterExternalChangeCallback

4

1 回答 1

2

首先,我建议向 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)
    }
}
于 2016-04-27T19:42:55.940 回答