Post

Replies

Boosts

Views

Activity

Reply to Can the NSPersistentCloudKitContainer mirror the data from the cloudKit public database to the local Core Data if the user is not logged in?
Here is the code that works only if the user is logged in. Again, I'm connecting to the Public database. class CoreDataManager: ObservableObject{ // Singleton static let instance = CoreDataManager() private let queue = DispatchQueue(label: "CoreDataManagerQueue") private var iCloudSync = true lazy var context: NSManagedObjectContext = { return container.viewContext }() lazy var container: NSPersistentContainer = { return setupContainer() }() func updateCloudKitContainer() { queue.sync { container = setupContainer() } } func setupContainer()->NSPersistentContainer{ let container = NSPersistentCloudKitContainer(name: "CoreDataContainer") guard let description = container.persistentStoreDescriptions.first else{ fatalError("###\(#function): Failed to retrieve a persistent store description.") } description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) let cloudKitContainerIdentifier = "iCloud.com.example.PublicDatabaseTest" let options = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier) description.cloudKitContainerOptions = options description.cloudKitContainerOptions?.databaseScope = .public // Specify Public Database 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() }catch let error{ print("Error saving Core Data. \(error.localizedDescription)") } } }
Jun ’24
Reply to How to save to specific stores/configurations in Core Data
After days of trying different things, I accidentally found out that the order of descriptions in the container array plays a crucial role in how Core Data prioritizes loading configurations and saving entities. In my original code, I was loading the default configuration first as shown below... guard let description = container.persistentStoreDescriptions.first else{ fatalError("###\(#function): Failed to retrieve a persistent store description.") } Then I was appending the public configuration as follows... container.persistentStoreDescriptions.append(publicDescription) Leaving the public configuration at the end of the persistentStoreDescriptions array, and apparently, the way Core Data works is that it searches the first configuration, and if the entity you're saving exists in the first configuration, it saves it in that configuration otherwise it keeps looping through all configs until it finds the entity in one of the configurations but since (by default) the Default configuration contains all entities, it was always saving to the default configuration so, the solution is to always leave the default configuration as the last item in the array. Solution: Here is what I did that solved my issue: Replaced this line... container.persistentStoreDescriptions.append(publicDescription) with... container.persistentStoreDescriptions = [publicDescription, description] Again, I basically added the Public configuration to the first configuration in the array. The key here is to always leave the default configuration at last, regardless of how many configurations you have. FYI - The sample project from the Linking Data Between two Core Data Stores led me to try to reorder the configurations in the array. https://developer.apple.com/documentation/coredata/linking_data_between_two_core_data_stores
Jul ’24
Reply to Can the NSPersistentCloudKitContainer mirror the data from the cloudKit public database to the local Core Data if the user is not logged in?
Here is the code that works only if the user is logged in. Again, I'm connecting to the Public database. class CoreDataManager: ObservableObject{ // Singleton static let instance = CoreDataManager() private let queue = DispatchQueue(label: "CoreDataManagerQueue") private var iCloudSync = true lazy var context: NSManagedObjectContext = { return container.viewContext }() lazy var container: NSPersistentContainer = { return setupContainer() }() func updateCloudKitContainer() { queue.sync { container = setupContainer() } } func setupContainer()->NSPersistentContainer{ let container = NSPersistentCloudKitContainer(name: "CoreDataContainer") guard let description = container.persistentStoreDescriptions.first else{ fatalError("###\(#function): Failed to retrieve a persistent store description.") } description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) let cloudKitContainerIdentifier = "iCloud.com.example.PublicDatabaseTest" let options = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier) description.cloudKitContainerOptions = options description.cloudKitContainerOptions?.databaseScope = .public // Specify Public Database 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() }catch let error{ print("Error saving Core Data. \(error.localizedDescription)") } } }
Replies
Boosts
Views
Activity
Jun ’24
Reply to iCloud sync doesn't work in production.
Just to make sure, when you say you deployed to production, are you referring to deploying the Schema changes in CloudKit? When using CoreData+CloudKit, you must deploy your schema once you're ready for production. Go to the CloudKit console, look for Deploy Schema Changes, and click on it.
Replies
Boosts
Views
Activity
Jun ’24
Reply to How can a user change some data in the public data base?
I don't think you can delete data created by other users, in what scenario would you want to delete the data created by another user? If what you really want, is for you as the main admin to be able to delete data other users created, I think you can do it directly in the ClouldKit console.
Replies
Boosts
Views
Activity
Jun ’24
Reply to Can the NSPersistentCloudKitContainer mirror the data from the cloudKit public database to the local Core Data if the user is not logged in?
Just to clarify, the error shown in my original post is not an error that makes the app crash, it's an error I get in the debug console, I assume it's an error logged by CloudKit.
Replies
Boosts
Views
Activity
Jun ’24
Reply to How to save to specific stores/configurations in Core Data
After days of trying different things, I accidentally found out that the order of descriptions in the container array plays a crucial role in how Core Data prioritizes loading configurations and saving entities. In my original code, I was loading the default configuration first as shown below... guard let description = container.persistentStoreDescriptions.first else{ fatalError("###\(#function): Failed to retrieve a persistent store description.") } Then I was appending the public configuration as follows... container.persistentStoreDescriptions.append(publicDescription) Leaving the public configuration at the end of the persistentStoreDescriptions array, and apparently, the way Core Data works is that it searches the first configuration, and if the entity you're saving exists in the first configuration, it saves it in that configuration otherwise it keeps looping through all configs until it finds the entity in one of the configurations but since (by default) the Default configuration contains all entities, it was always saving to the default configuration so, the solution is to always leave the default configuration as the last item in the array. Solution: Here is what I did that solved my issue: Replaced this line... container.persistentStoreDescriptions.append(publicDescription) with... container.persistentStoreDescriptions = [publicDescription, description] Again, I basically added the Public configuration to the first configuration in the array. The key here is to always leave the default configuration at last, regardless of how many configurations you have. FYI - The sample project from the Linking Data Between two Core Data Stores led me to try to reorder the configurations in the array. https://developer.apple.com/documentation/coredata/linking_data_between_two_core_data_stores
Replies
Boosts
Views
Activity
Jul ’24