c我在共享的Cloudkit数据库中有记录,但在应用运行时对这些记录进行更改(创建、更新或删除)时,我没有收到任何通知。如果我重新启动应用程序,我会看到更改。
据我所知,我需要使用CKDatabaseSubscription注册共享Cloudkit数据库中的更改。这是我目前所拥有的:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
application.registerForRemoteNotifications()
// Create database subscription to look for changes
let subscription = CKDatabaseSubscription(subscriptionID: "todoChanges")
// Does this need to be CD_Todo?
subscription.recordType = "Todo"
let notificationInfo = CKSubscription.NotificationInfo()
notificationInfo.shouldSendContentAvailable = true
subscription.notificationInfo = notificationInfo
// Save to server
let operation = CKModifySubscriptionsOperation(subscriptionsToSave: [subscription], subscriptionIDsToDelete: nil)
operation.modifySubscriptionsCompletionBlock = { subscriptions, deleted, error in
if let error = error {
// Handle the error.
} else {
// ... cache/store in UserDefaults?
}
}
operation.qualityOfService = .utility
CKContainer.default().sharedCloudDatabase.add(operation)
// Additional bits for SceneDelegate
let config = UISceneConfiguration(
name : nil,
sessionRole : connectingSceneSession.role
)
config.delegateClass = SceneDelegate.self
return config
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("Change made in shared database")
}
}
字符串
对于上面的代码,我不确定是否需要使用subscription.recordType
的CoreData实体名称(“Todo”)或Cloudkit名称(“CD_Todo”)。话虽如此,但似乎都不起作用。
我还将订阅附加到共享数据库,我认为这是正确的,因为我希望在那里监视更改。我可以在iCloud Jmeter 板的“订阅”部分中看到订阅,这样我就可以验证它是否已保存。
除了上述我有“远程通知”选择的背景模式。我不认为我需要“背景提取”,无论如何启用它似乎没有什么区别。
在这一点上,我想做的就是让通知工作。最后,我希望应用程序在收到更改通知时获取最新的更改,但我似乎无法让第一部分工作,这最终会触发获取。
为了测试这一点,我一直在通过 Jmeter 板Web界面修改记录,但我没有看到“Change made in shared database”在Xcode中输出。据我所知,共享数据库是正确链接的,因为 Jmeter 板中所做的更改会在下次启动(或重新启动)时反映在我的应用程序中。
1条答案
按热度按时间izkcnapc1#
所以,我已经解决了我的问题,但我将在上下文中完整地解释这个问题。
我正在构建一个应用程序,该应用程序可以在区域范围内共享,以促进区域中所有记录之间的共享(而不是显式记录)。
之所以想得到通知,是因为我只得到了两个设备之间的单向同步。也就是说,设备A(iPhone)是所有者(私有数据库),设备B(模拟器)是参与者(共享数据库,具有对属于设备A的记录的读写权限)。在这个场景中,我可以从设备B创建/更新/删除Todo条目,它们会出现在设备A上,但反过来就不行了(除非我在设备B上重新启动应用程序)。这就是为什么我沿着通知的路径走下去--只是为了看看设备B是否至少在设备A做出更改时收到了一些东西。
然而,我随后想到颠倒共享的角色,以便设备A(iPhone)成为参与者,设备B(模拟器)成为所有者。在这个场景中,数据库被交换,设备A现在使用共享数据库,设备B使用私有数据库(由NSPersistentCloudkitContainer自动处理)。同样的事情发生了:更新从设备B到设备A(模拟器-> iPhone),而不是相反(iPhone ->模拟器)。然而,由于我交换了角色,因此数据库(我不确定共享数据库在幕后的行为是否与私有数据库不同),它指向了模拟器的一个问题(这开始是一个怀疑)。
无论如何,我通过在我的伴侣的设备上安装应用程序来确认这一点,并且立即在两个方向上共享工作。此外,它不需要任何订阅通知代码,如我上面的示例所示。我不知道是该哭还是该笑,因为我已经在这个问题上被卡住了,在房子里转了三天。
因此,如果有人发现这篇文章,并且遇到类似的问题,请尝试在两个物理设备之间进行设置(如果可以的话),因为它会出现,至少在我的情况下,模拟器在参与共享时不会收到更改通知。这是非常令人恼火的,因为苹果文档中没有提到这一点(据我所知),如果不参与共享,它将响应通过Cloudkit Jmeter 板进行的更改。
就我的应用程序的其余部分而言,我并没有真正偏离苹果的例子,在设置NSPersistentCloudkitContainer与私人和共享数据库(例如。https://developer.apple.com/videos/play/wwdc2021/10015/?time=1264)但这就是我需要做的一切。我当然不需要创建过程来手动获取和更新本地数据,这似乎与他们的解释相反,但也许CloudKit近年来已经发展到承担更多必要的繁重工作。