swift 为什么我的手表应用无法查看来自iOS Core Data应用的数据?

9nvpjoqh  于 2024-01-05  发布在  Swift
关注(0)|答案(1)|浏览(137)

我一直在沿着一个Hacking with Swift教程,他制作了一个应用程序,可以在iPhone,iPad和Mac版本的应用程序之间同步数据。所有的同步都由Core Data和Cloud Kit处理。
我一直在尝试将他所做的调整到我自己的应用程序中,该应用程序有一个配套的watchOS应用程序。
我将iOS应用和watchOS应用放在同一个应用组中,并使用正确的应用组标识符加载共享应用容器(我的小部件可以正常看到数据),但watch应用永远看不到数据。watch应用不会崩溃,它只是看不到任何要加载的内容,我得到的是一个空的实体数组。
手表应用程序可以不使用这种方法吗?我是否错过了一些关键步骤?
下面是DataController类:

  1. import CoreData
  2. import SwiftUI
  3. class DataController: ObservableObject {
  4. let container: NSPersistentCloudKitContainer
  5. private var saveTask: Task<Void, Error>?
  6. static var preview: DataController = {
  7. let dataController = DataController(inMemory: true)
  8. return dataController
  9. }()
  10. private var sharedStoreURL: URL {
  11. let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.MyCo.MyApp1")!
  12. return container.appendingPathComponent("Model.sqlite")
  13. }
  14. static let model: NSManagedObjectModel = {
  15. guard let url = Bundle.main.url(forResource: "Model", withExtension: "momd") else {
  16. fatalError("Failed to locate model file.")
  17. }
  18. guard let managedObjectModel = NSManagedObjectModel(contentsOf: url) else {
  19. fatalError("Failed to load model file.")
  20. }
  21. return managedObjectModel
  22. }()
  23. init(inMemory: Bool = false) {
  24. container = NSPersistentCloudKitContainer(name: "Model", managedObjectModel: Self.model)
  25. if inMemory {
  26. container.persistentStoreDescriptions.first?.url = URL(filePath: "/dev/null")
  27. } else {
  28. container.persistentStoreDescriptions.first?.url = sharedStoreURL
  29. }
  30. container.viewContext.automaticallyMergesChangesFromParent = true
  31. container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
  32. container.persistentStoreDescriptions.first?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
  33. NotificationCenter.default.addObserver(forName: .NSPersistentStoreRemoteChange, object: container.persistentStoreCoordinator, queue: .main, using: remoteStoreChanged)
  34. container.loadPersistentStores { _, error in
  35. if let error {
  36. fatalError("Fatal error loading store: \(error.localizedDescription)")
  37. }
  38. }
  39. }
  40. func remoteStoreChanged(_ notification: Notification) {
  41. objectWillChange.send()
  42. }
  43. func save() {
  44. saveTask?.cancel()
  45. if container.viewContext.hasChanges {
  46. try? container.viewContext.save()
  47. }
  48. }
  49. func queueSave() {
  50. saveTask?.cancel()
  51. saveTask = Task { @MainActor in
  52. try await Task.sleep(for: .seconds(3))
  53. save()
  54. }
  55. }
  56. func delete(_ object: NSManagedObject) {
  57. objectWillChange.send()
  58. container.viewContext.delete(object)
  59. save()
  60. }
  61. private func delete(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
  62. let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
  63. batchDeleteRequest.resultType = .resultTypeObjectIDs
  64. if let delete = try? container.viewContext.execute(batchDeleteRequest) as? NSBatchDeleteResult {
  65. let changes = [NSDeletedObjectsKey: delete.result as? [NSManagedObjectID] ?? []]
  66. NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [container.viewContext])
  67. }
  68. }
  69. func getMyEntities() throws -> [MyEntity] {
  70. let request: NSFetchRequest<MyEntity> = MyEntity.fetchRequest()
  71. request.sortDescriptors = [NSSortDescriptor(keyPath: \MyEntity.name, ascending: true)]
  72. let entities = try container.viewContext.fetch(request)
  73. return entities
  74. }

字符串
}
编辑--我缺少的关键部分是为iOS应用程序目标和watchOS应用程序目标添加两个功能。
首先,我需要在选择CloudKit服务的情况下添加iCloud功能,并创建一个要在iOS应用程序和watchOS应用程序之间共享的容器。
其次,我需要添加后台模式功能,并选择后台获取模式(仅适用于iOS)和远程通知模式(iOS和watchOS)。

56lgkhnf

56lgkhnf1#

AppGroup容器用于同一设备中的应用程序。这就是为什么它在iOS应用程序和Widget之间工作。
AppGroups使用“进程间通信(IPC)”,这发生在设备上的共享内存中。AppGroups不支持iCloud或任何其他允许WatchOS连接的同步进程。
如果您想在iOS和WatchOS之间共享数据,可以使用CloudKit并在设备之间共享相同的iCloud容器,或者使用WatchConnectivity将新数据发送到WatchOS。
Hacking With Swift视频可能使用相同的CloudKit容器,这是最简单的选择。只需确保所有目标都匹配“签名和功能”
这里有一些有用的链接。
https://developer.apple.com/wwdc21/10003
https://developer.apple.com/documentation/coredata/mirroring_a_core_data_store_with_cloudkit/setting_up_core_data_with_cloudkit
https://developer.apple.com/documentation/watchconnectivity/implementing_two-way_communication_using_watch_connectivity

相关问题