I've understood that SwiftData is not abled to share the whole content of a cloudkit database.
So I'm trying to rewrite everything. Does someone knows id Sharing is coming on SwiftData at WWDC 26?
Anyway, can someone can point me an example a a configured coredata stack that share all its content with other icloud users (with sharing pane and accept invitation code).
At this step, on the owner side, I see some data in the default zone of my private container but nothing is visible on the shared zone. Maybe I don't understand where and when I should check shared data in cloudkit console. Need Help also here.
See below by configuration stack:
// Core Data container
public lazy var container: NSPersistentContainer = {
switch delegate.usage() {
case .preview : return previewContainer()
case .local : return localContainer()
case .cloudKit : return cloudKitContainer()
}
}()
private func cloudKitContainer() -> NSPersistentContainer {
let modelURL = delegate.modelURL()
let modelName = modelURL.deletingPathExtension().lastPathComponent
guard let model = NSManagedObjectModel(contentsOf: modelURL) else {
fatalError("Could not load Core Data model from \(modelURL)")
}
let container = NSPersistentCloudKitContainer(
name: modelName,
managedObjectModel: model
)
let groupIdentifier = AppManager.shared.groupIdentifier
guard let appGroupURL = FileManager.default.containerURL (
forSecurityApplicationGroupIdentifier: groupIdentifier
) else {
fatalError("App Group not found: \(groupIdentifier)")
}
// MARK: - Private Store Configuration
let privateStoreURL = appGroupURL.appendingPathComponent("\(modelName).sqlite")
let privateStoreDescription = NSPersistentStoreDescription(url: privateStoreURL)
// Persistent history tracking (MANDATORY)
privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
// CloudKit options for private database
// Core Data automatically uses the default zone: com.apple.coredata.cloudkit.zone
let privateCloudKitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: delegate.cloudKitIdentifier())
privateCloudKitOptions.databaseScope = .private
privateStoreDescription.cloudKitContainerOptions = privateCloudKitOptions
// MARK: - Shared Store Configuration
guard let sharedStoreDescription = privateStoreDescription.copy() as? NSPersistentStoreDescription else {
fatalError("Create shareDesc error")
}
// The shared store receives zones that others share with us via CloudKit's shared database
sharedStoreDescription.url = appGroupURL.appendingPathComponent("\(modelName)-shared.sqlite")
// Persistent history tracking (MANDATORY)
sharedStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
sharedStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
// CloudKit options for shared database
// This syncs data from CloudKit shared zones when we accept share invitations
let sharedCloudKitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: delegate.cloudKitIdentifier())
sharedCloudKitOptions.databaseScope = .shared
sharedStoreDescription.cloudKitContainerOptions = sharedCloudKitOptions
// Configure both stores
// Private store: com.apple.coredata.cloudkit.zone in private database
// Shared store: Receives shared zones we're invited to
container.persistentStoreDescriptions = [privateStoreDescription, sharedStoreDescription]
container.loadPersistentStores { storeDescription, error in
if let error = error as NSError? {
fatalError("DB init error:\(error.localizedDescription)")
} else if let cloudKitContiainerOptions = storeDescription.cloudKitContainerOptions {
switch cloudKitContiainerOptions.databaseScope {
case .private:
self._privatePersistentStore = container.persistentStoreCoordinator.persistentStore(for: privateStoreDescription.url!)
case .shared:
self._sharedPersistentStore = container.persistentStoreCoordinator.persistentStore(for: sharedStoreDescription.url!)
default:
break
}
}
let scope = storeDescription.cloudKitContainerOptions?.databaseScope == .shared ? "shared" : "private"
print("✅ \(scope) store loaded at: \(storeDescription.url?.path ?? "unknown")")
}
// Auto-merge
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
do {
try container.viewContext.setQueryGenerationFrom(.current)
} catch {
fatalError("Fail to pin viewContext to the current generation:\(error)")
}
return container
}
You are right that there is no way to share a ClodKit database. An owner can only share a custom record zone in their private database. The default record zone doesn’t support sharing, mentioned here.
To share "the whole content of a cloudkit database," the following may be worth considering :
-
When an owner shares a custom record zone, all the data in the record zone is shared, and so you an share your dataset by putting the dataset into the zone.
-
All your app users have access to the public database of your CloudKit container, and you can build your own user management system to control the access. Based on this, you might be able to "share" your data by using the public database instead.
To get more information about CloudKit sharing, you might go through this sample code.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.