Post

Replies

Boosts

Views

Created

Can the NSPersistentCloudKitContainer mirror the data from the cloudKit public database to the local Core Data if the user is not logged in?
I'm currently syncing Core Data with the CloudKit public database using NSPersistentCloudKitContainer. The app starts with an empty Core Data store locally and at the app launch it downloads the data from CloudKit public database to the Core Data store, but this can only be accomplished if the user is logged in, if the user is not logged, no data gets downloaded and I get the error below. Can the NSPersistentCloudKitContainer mirror the data from the CloudKit public database to the local Core Data even if the user is not logged in? Can someone please confirm this is possible? The reason for my question is because I was under the impression that the users didn't need to be logged to read data from the public database in CloudKit but I'm not sure this applies to NSPersistentCloudKitContainer when mirroring data. I know I can fetch data directly with CloudKit APIs without the user beign logged but I need to understand if NSPersistentCloudKitContainer should in theory work without the user being logged. I hope someone from Apple sees this question since I have spent too much time researching without any luck. Error Error fetching user record ID: <CKError 0x600000cb1b00: "Not Authenticated" (9); "No iCloud account is configured"> CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1192): <NSCloudKitMirroringDelegate: 0x600003b00460>: Failed to set up CloudKit integration for store: <NSSQLCore: 0x10700f0d0> (URL: file:///Users/UserName/...
4
0
975
Jun ’24
How to save to specific stores/configurations in Core Data
I'm currently syncing core data with the CloudKit private and public databases, as you can see in the code below, I'm saving the private database in the default configuration in Core Data and the public in a configuration called Public everything works fine when NSPersistentCloudKitContainer syncs, what I'm having an issue with is trying to save to the public data store PublicStore, for instance when I try to save with func createIconImage(imageName: String) it saves the image to the "default" store, not the PublicStore(Public configuration). What could I do to make the createIconImage() function save to the PublicStore sqlite database? class CoreDataManager: ObservableObject{ static let instance = CoreDataManager() private let queue = DispatchQueue(label: "CoreDataManagerQueue") @AppStorage(UserDefaults.Keys.iCloudSyncKey) private var iCloudSync = false lazy var context: NSManagedObjectContext = { return container.viewContext }() lazy var container: NSPersistentContainer = { return setupContainer() }() init(inMemory: Bool = false){ if inMemory { container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") } } func updateCloudKitContainer() { queue.sync { container = setupContainer() } } private func getDocumentsDirectory() -> URL { return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] } private func getStoreURL(for storeName: String) -> URL { return getDocumentsDirectory().appendingPathComponent("\(storeName).sqlite") } func setupContainer()->NSPersistentContainer{ let container = NSPersistentCloudKitContainer(name: "CoreDataContainer") let cloudKitContainerIdentifier = "iCloud.com.example.MyAppName" guard let description = container.persistentStoreDescriptions.first else{ fatalError("###\(#function): Failed to retrieve a persistent store description.") } description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) if iCloudSync{ if description.cloudKitContainerOptions == nil { let options = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier) description.cloudKitContainerOptions = options } }else{ print("Turning iCloud Sync OFF... ") description.cloudKitContainerOptions = nil } // Setup public database let publicDescription = NSPersistentStoreDescription(url: getStoreURL(for: "PublicStore")) publicDescription.configuration = "Public" // this is the configuration name if publicDescription.cloudKitContainerOptions == nil { let publicOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier) publicOptions.databaseScope = .public publicDescription.cloudKitContainerOptions = publicOptions } container.persistentStoreDescriptions.append(publicDescription) container.loadPersistentStores { (description, error) in if let error = error{ print("Error loading Core Data. \(error)") } } container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy return container } func save(){ do{ try context.save() //print("Saved successfully!") }catch let error{ print("Error saving Core Data. \(error.localizedDescription)") } } } class PublicViewModel: ObservableObject { let manager: CoreDataManager @Published var publicIcons: [PublicServiceIconImage] = [] init(coreDataManager: CoreDataManager = .instance) { self.manager = coreDataManager } func createIconImage(imageName: String) { let newImage = PublicServiceIconImage(context: manager.context) newImage.imageName = imageName newImage.id = UUID() save() } func save() { self.manager.save() } }
1
0
715
Jul ’24