23

非推奨の Address Book Framework から新しい Contacts Framework にアプリケーションを移行しています。ABAddressBookRegisterExternalChangeCallbackアプリケーションは、別のアプリケーションが連絡先を変更したときに通知を受け取るために利用します。

Contacts Framework で同等の機能を見つけることができません。Apple のドキュメントでは、通知でデフォルトの通知センターを使用するように指示されてCNContactStoreDidChangeNotificationます

別の で変更が発生したときに投稿される通知CNContactStore

Apple のアドバイスを受けて、私のコードは次のようになります。

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

ただし、このアプローチには 2 つの問題があることがわかりました。

  1. 自分のアプリケーションによるものを含め、すべての変更について通知されます。
  2. 偽の通知 - 1 つの変更に対して多くの通知を受け取ります。

アプリ内で変更が行われたときに通知のデバッグの説明をログに記録すると、次のようになります。

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

また、変更が外部で行われた場合:

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

ご覧のとおり、それらを区別する明確なものは何もありません。

から取得できるのと同じ動作を Contacts Framework から取得する方法を誰か教えてもらえますABAddressBookRegisterExternalChangeCallbackか?

4

1 に答える 1

2

まず、API の内部と外部の変更を識別する方法がないことについて、Apple にバグを報告することをお勧めします。

可能な回避策として、変更を行う前にオブザーバーの登録を解除し、変更直後に再登録することで、すべての変更通知を見逃しても、すべての外部通知を確実に取得できるかどうかを確認できます。

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 に答える