为何我的watchOS应用无法读取iOS Core Data应用中的数据?
watchOS 应用使用
NSPersistentCloudKitContainer 无法读取 Core Data 数据 我跟着Hacking with Swift教程开发了一款支持iPhone、iPad和Mac端数据同步的应用,用Core Data + CloudKit实现同步。现在想把这套方案适配到带watchOS配套应用的项目里,用了NSPersistentCloudKitContainer。
已经把iOS和watchOS应用加入同一个App Group,也通过正确的App Group标识符加载了共享容器(小组件能正常读取数据),但watchOS应用始终读不到数据,不会崩溃,只是返回空的实体数组。
想问watchOS是否不支持这种方法?还是我漏了关键步骤?
以下是我的DataController类代码:
import CoreData import SwiftUI class DataController: ObservableObject { let container: NSPersistentCloudKitContainer private var saveTask: Task<Void, Error>? static var preview: DataController = { let dataController = DataController(inMemory: true) return dataController }() private var sharedStoreURL: URL { let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.MyCo.MyApp1")! return container.appendingPathComponent("Model.sqlite") } static let model: NSManagedObjectModel = { guard let url = Bundle.main.url(forResource: "Model", withExtension: "momd") else { fatalError("Failed to locate model file.") } guard let managedObjectModel = NSManagedObjectModel(contentsOf: url) else { fatalError("Failed to load model file.") } return managedObjectModel }() init(inMemory: Bool = false) { container = NSPersistentCloudKitContainer(name: "Model", managedObjectModel: Self.model) if inMemory { container.persistentStoreDescriptions.first?.url = URL(filePath: "/dev/null") } else { container.persistentStoreDescriptions.first?.url = sharedStoreURL } container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump container.persistentStoreDescriptions.first?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) NotificationCenter.default.addObserver(forName: .NSPersistentStoreRemoteChange, object: container.persistentStoreCoordinator, queue: .main, using: remoteStoreChanged) container.loadPersistentStores { _, error in if let error { fatalError("Fatal error loading store: \(error.localizedDescription)") } } } func remoteStoreChanged(_ notification: Notification) { objectWillChange.send() } func save() { saveTask?.cancel() if container.viewContext.hasChanges { try? container.viewContext.save() } } func queueSave() { saveTask?.cancel() saveTask = Task { @MainActor in try await Task.sleep(for: .seconds(3)) save() } } func delete(_ object: NSManagedObject) { objectWillChange.send() container.viewContext.delete(object) save() } private func delete(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) { let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest) batchDeleteRequest.resultType = .resultTypeObjectIDs if let delete = try? container.viewContext.execute(batchDeleteRequest) as? NSBatchDeleteResult { let changes = [NSDeletedObjectsKey: delete.result as? [NSManagedObjectID] ?? []] NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [container.viewContext]) } } func getMyEntities() throws -> [MyEntity] { let request: NSFetchRequest<MyEntity> = MyEntity.fetchRequest() request.sortDescriptors = [NSSortDescriptor(keyPath: \MyEntity.name, ascending: true)] let entities = try container.viewContext.fetch(request) return entities }
解决方案(补充编辑)
问题出在遗漏了两项关键的功能权限配置,需要给iOS和watchOS应用目标都添加:
- 添加iCloud功能:选择CloudKit服务,并创建一个iOS与watchOS共享的容器;
- 添加Background Modes功能:iOS需勾选
Background fetch模式,iOS和watchOS都要勾选Remote notifications模式。
内容的提问来源于stack exchange,提问作者Legion
相关产品推荐
相关产品推荐

