Contact Framework等效于ABAddressBook.ABAddressBookRegisterExternalChangeCallback

me-*_*e-- 22 abaddressbook ios swift cncontact cncontactstore

我正在将已弃用的通讯簿框架中的应用程序迁移到新的"联系人框架".该应用程序使用ABAddressBookRegisterExternalChangeCallback时,另一个应用程序更改联系人通知.

我无法在Contacts Framework中找到相同的功能.苹果文件说,将使用与默认通知中心的CNContactStoreDidChangeNotification通知:

在另一个更改发生时发布通知CNContactStore.

根据Apple的建议,我的代码如下:

NSNotificationCenter.defaultCenter().addObserver(
    self,
    selector: "contactsChanged:",
    name: CNContactStoreDidChangeNotification,
    object: nil)
Run Code Online (Sandbox Code Playgroud)

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

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

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

NSConcreteNotification 0x7d3370e0 {name = CNContactStoreDidChangeNotification; userInfo = {
    CNNotificationOriginationExternally = 1;
    CNNotificationSourcesKey =     (
    );
}}
Run Code Online (Sandbox Code Playgroud)

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

NSConcreteNotification 0x7bf7a690 {name = CNContactStoreDidChangeNotification; userInfo = {
    CNNotificationOriginationExternally = 1;
    CNNotificationSourcesKey =     (
    );
}}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,没有什么明显可以区分它们.

任何人都可以告诉我如何从联系人框架中获得相同的行为,因为人们可以得到ABAddressBookRegisterExternalChangeCallback?

ric*_*ter 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)
    }
}
Run Code Online (Sandbox Code Playgroud)