Swift CloudKit CoreData 远程更改通知也针对本地更改触发
Swift CloudKit CoreData Remote Change Notification also firing for local changes
我有一个带有 Local 存储和 Cloud 存储的 CoreData 设置,只有后者与 [=38= 同步].同步本身运行良好。
我正在尝试监听远程更改通知,以便当来自 CloudKit 的远程更改进入时,我可以在设备上触发一些进程。我已经设置了 NSPersistentStoreRemoteChangeNotificationOptionKey
键我的持久性控制器,以及相应的监听器。
观察者正确触发远程更改通知,但我的问题是,一旦保存视图上下文,也会触发设备上产生的任何 CoreData 更改。
如果这是预期的行为,我希望通知本身至少会有一些有用的信息,这样我就可以区分更改是由设备上的操作触发的还是从 CloudKit 同步的.
有没有我做错了什么,或者有任何其他简单的方法可以在发生远程更改时收到通知?
持久化控制器
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init() {
container = NSPersistentCloudKitContainer(name: "MyContainerName")
let storeDirectory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
// Local
let localUrl = storeDirectory.appendingPathComponent("local.store")
let local = NSPersistentStoreDescription(url: localUrl)
local.configuration = "Local"
// Cloud
let cloudUrl = storeDirectory.appendingPathComponent("cloud.store")
let cloud = NSPersistentStoreDescription(url: cloudUrl)
cloud.configuration = "Cloud"
cloud.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "my.container.identifier")
cloud.setOption(true as NSNumber, forKey: "NSPersistentStoreRemoteChangeNotificationOptionKey")
container.persistentStoreDescriptions = [local, cloud]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
}
应用委托
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
NotificationCenter.default.addObserver(
self, selector: #selector(type(of: self).storeRemoteChange(_:)),
name: .NSPersistentStoreRemoteChange,
object: PersistenceController.shared.container.persistentStoreCoordinator
)
return true
}
@objc
func storeRemoteChange(_ notification: Notification) {
precondition(notification.name == NSNotification.Name.NSPersistentStoreRemoteChange)
print(notification.userInfo)
}
}
打印语句的输出
Optional([AnyHashable("NSStoreUUID"): C2D121212-421B-003F-9819-956411111169, AnyHashable("storeURL"): file:///var/mobile/Containers/Data/Application/3234FH#-DACF-493I-AD24-143E4CDSFE2/Library/Application%20Support/cloud.store])
If this is expected behaviour, I was hoping there would at least be some useful information in the notification itself so I could tell apart whether the change was triggered by an on-device action or synced from CloudKit.
是的,这是预期的行为,因为无论是在本地设备上还是从云中更改,这都会记录为您 store/database 中的更改。
因此,为了处理来自云的更改,您可以订阅数据库更改,阅读 here
我有一个带有 Local 存储和 Cloud 存储的 CoreData 设置,只有后者与 [=38= 同步].同步本身运行良好。
我正在尝试监听远程更改通知,以便当来自 CloudKit 的远程更改进入时,我可以在设备上触发一些进程。我已经设置了 NSPersistentStoreRemoteChangeNotificationOptionKey
键我的持久性控制器,以及相应的监听器。
观察者正确触发远程更改通知,但我的问题是,一旦保存视图上下文,也会触发设备上产生的任何 CoreData 更改。
如果这是预期的行为,我希望通知本身至少会有一些有用的信息,这样我就可以区分更改是由设备上的操作触发的还是从 CloudKit 同步的.
有没有我做错了什么,或者有任何其他简单的方法可以在发生远程更改时收到通知?
持久化控制器
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init() {
container = NSPersistentCloudKitContainer(name: "MyContainerName")
let storeDirectory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
// Local
let localUrl = storeDirectory.appendingPathComponent("local.store")
let local = NSPersistentStoreDescription(url: localUrl)
local.configuration = "Local"
// Cloud
let cloudUrl = storeDirectory.appendingPathComponent("cloud.store")
let cloud = NSPersistentStoreDescription(url: cloudUrl)
cloud.configuration = "Cloud"
cloud.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "my.container.identifier")
cloud.setOption(true as NSNumber, forKey: "NSPersistentStoreRemoteChangeNotificationOptionKey")
container.persistentStoreDescriptions = [local, cloud]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
}
应用委托
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
NotificationCenter.default.addObserver(
self, selector: #selector(type(of: self).storeRemoteChange(_:)),
name: .NSPersistentStoreRemoteChange,
object: PersistenceController.shared.container.persistentStoreCoordinator
)
return true
}
@objc
func storeRemoteChange(_ notification: Notification) {
precondition(notification.name == NSNotification.Name.NSPersistentStoreRemoteChange)
print(notification.userInfo)
}
}
打印语句的输出
Optional([AnyHashable("NSStoreUUID"): C2D121212-421B-003F-9819-956411111169, AnyHashable("storeURL"): file:///var/mobile/Containers/Data/Application/3234FH#-DACF-493I-AD24-143E4CDSFE2/Library/Application%20Support/cloud.store])
If this is expected behaviour, I was hoping there would at least be some useful information in the notification itself so I could tell apart whether the change was triggered by an on-device action or synced from CloudKit.
是的,这是预期的行为,因为无论是在本地设备上还是从云中更改,这都会记录为您 store/database 中的更改。
因此,为了处理来自云的更改,您可以订阅数据库更改,阅读 here