NSPersistentCloudKitContainer
を使用するCoreData + CloudKitプロジェクトで履歴追跡を実行しようとしています。私はAppleの サンプルプロジェクト と一緒にフォローしています
リモートストアが更新されたときに特定のタスクを実行したい。このため、Appleは、アプリの署名と機能のバックグラウンドモードセクションでリモート通知を有効にすることをお勧めします。
Appleのサンプルプロジェクトに示されているように、プロジェクトの履歴追跡を有効にしました。
// turn on persistent history tracking
let description = container.persistentStoreDescriptions.first
description?.setOption(true as NSNumber,
forKey: NSPersistentHistoryTrackingKey)
// ...
また、ストアの変更をリッスンするためにストアを登録しました。
// turn on remote change notifications
let remoteChangeKey = "NSPersistentStoreRemoteChangeNotificationOptionKey"
description?.setOption(true as NSNumber,
forKey: remoteChangeKey)
// ...
NSPersistentStoreRemoteChangeNotification
をリッスンするオブザーバーも追加されています。
ただし、NSPersistentStoreRemoteChangeNotification
は起動されません。実装に間違いがないことを確認するために、Appleが提供するサンプルコード@objc func storeRemoteChange(_ notification: Notification)
にブレークポイントを設定しただけですが、通知が発行されておらず、ブレークポイントがアクティブ化されていません。
サンプルプロジェクトで行われたタグの重複排除を理解し、テストも試みましたが、成功しませんでした。それはAppleの実装のバグですか、それとも必要なセットアップがありませんか?
OPによって言及されたサンプルアプリをデバッグすると、次のことがわかりました。
NSPersistentStoreRemoteChangeNotificationPostOptionKey
)と通知名(.NSPersistentStoreRemoteChange
)の両方にSDK定数があり、これらはサンプルの最新のダウンロードに反映されています。コード。NSFetchedResultsController
デリゲートがcontrollerDidChangeContent
コールバックを使用してUIを更新することによって促されます。NSPersistentCloudKitContainer
は、クラウドから送信されたすべての更新のローカル永続ストアへの自動インポートを実行します。これは、persistentStoreが履歴追跡用に設定され、viewContextが自動更新用に設定されているためです。最新世代のデータに対して、インポートごとにUIの更新がトリガーされます。これらの観察に基づいて、CoreData、CloudKit、およびSwiftUIの使用を指定して取得したXCodeテンプレートに基づいて、小さなアプリを最初から作成しました。サンプルアプリで設定したのと同じ方法で永続コンテナーとビューコンテキストを設定し、SwiftUIの@FetchRequest
ラッパーを使用してマスタービュー表示でデータを取得しました。案の定、リモートインポートの動作はまったく同じでしたなしリモート変更通知を使用し、インポートのたびにUIが更新されました。
次に、受け入れられた回答に従って、リモート変更通知に正しく登録すると、それらが受信されることを確認しました。これらは、NSPersistentCloudKitでの各受信およびインポート操作が完了した後に送信されるようです。それらのインポートによって開始されたローカルデータの変更の通知を取得するために、それらを監視する必要はありません。
バグかどうかわかりません。 Appleのサンプルプロジェクトをダウンロードして実行するだけですが、NSPersistentStoreRemoteChangeNotification
が起動されることはありません。
AppDelegateに同じNSPersistentStoreRemoteChangeNotification
のオブザーバーをもう1つ追加しましたが、起動しています。
AppDelegateに通知オブザーバーを追加してから、CoreDataStackのStoreRemoteChange(_:)
を呼び出すだけです。また、タグ重複排除ロジックは正しく機能します。
これがAppDelegateに追加したコードです
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// The view controller hierarchy is defined in the main storyboard.
guard let splitViewController = window?.rootViewController as? UISplitViewController,
let navController = splitViewController.viewControllers[splitViewController.viewControllers.count - 1] as? UINavigationController,
let topViewController = navController.topViewController else {
return false
}
// Configure the splitViewController.
topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
splitViewController.delegate = self
splitViewController.preferredDisplayMode = .allVisible
// Observe Core Data remote change notifications.
NotificationCenter.default.addObserver(
self, selector: #selector(type(of: self).storeRemoteChange(_:)),
name: .NSPersistentStoreRemoteChange, object: nil)
return true
}
@objc
func storeRemoteChange(_ notification: Notification) {
coreDataStack.storeRemoteChange(notification)
}