I've been searching all over the web trying to find the proper way to get all records created by a specific user in CloudKit.
I am able to get the correct id using:
guard let userRecordID = try? await container.userRecordID() else { return }
I can see that the id returned is associated with records in my CloudKit dashboard. So I would expect that the following would get those records:
let predicate = NSPredicate(format: "%K == %@", #keyPath(CKRecord.creatorUserRecordID), userRecordID)
let query = CKQuery(recordType: "CKUser", predicate: predicate)
But instead when I use that query it returns nothing. It is successful but with nothing returned...
Any ideas why this would be happening?
P.S. I have also tried constructing the predicate using the reference, but I get the same result - success with no results.
P.S.2 Also worth mentioning that I am trying to get the results from the public database and I have set my CKContainer to the correct container id.
CloudKit
RSS for tagStore structured app and user data in iCloud containers that can be shared by all users of your app using CloudKit.
Posts under CloudKit tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Something has caused my CloudKit queries to fail. On the dashboard I get an error message "Failed to execute query" when I try to "SORT BY" a field. The field is listed under Indexes as "sortable". For a different field, when I enter the field under "FILTER BY", and before I tap "Query", I get "No results". That field is listed under the Indexes as "queryable".
It used to work fine.
I have described this further, with screenshots at FB16114560
First query works fine. If next query comes within 30 seconds of first query it generates a CKErrorRequestRateLimited (error.code==7) error telling me to try after a time such that there would be 30 seconds between queries.
<CKError 0x30299dd70: "Request Rate Limited" (7/2061); "Operation throttled by previous server http 503 reply. Retry after 20.5 seconds. (Other operations may be allowed.)"; Retry after 20.5 seconds>
I get this red warning in Xcode every time my app is syncing to the iCloud. My model has only basic types and enum that conform to Codable so i'm not sure what is the problem.
App is working well, synchronization works. But the warning doesn't look good.
Maybe someone has idea how to debug it.
Hi everyone. I created test-apps years ago. Now I looked into https://icloud.developer.apple.com/dashboard/
There I found these old apps listed.
How do I delete these Apps in the Console and entirely from my account?
I don't have the project files anymore.
All the best! 😊
Hi everyone,
I have an application that allows to share Core Data records through CKShare.
If I compile the app in debug or release mode on my devices with Xcode the Sharing functionality work like a charm, but if I download the application from App Store doesn't work, It seems that can't generate the link for sharing.
Does anyone have any idea why?
Thanks
Looking at my CloudKit Telemetry console I noticed a significant increase in 'Other' errors recently. These errors are impacting user experience and I really don't know how to better understand the issues that may be occurring due to the "other" category. If I query the logs for "other" errors, only 2 results show up for the week. There are 2500+ errors in the telemetry graph (see attached).
Is anyone else experiencing this or does anyone have a suggestion on how I can better understand this issue? Thank you!
Hi,
I'm building a habit tracking app for iOS and macOS. I want to use up to date technologies, so I'm using SwiftUI and SwiftData.
I want to store user data locally on device and also sync data between device and iCloud server so that the user could use the app conveniently on multiple devices (iPhone, iPad, Mac).
I already tried SwiftData + NSPersistentCloudKitContainer, but I need to control when to sync data, which I can't control with NSPersistentCloudKitContainer. For example, I want to upload data to server right after data is saved locally and download data from server on every app open, on pull-to-refresh etc. I also need to monitor sync progress, so I can update the UI and run code based on the progress. For example, when downloading data from server to device is in progress, show "Loading..." UI, and when downloading finishes, I want to run some app business logic code and update UI.
So I'm considering switching from NSPersistentCloudKitContainer to CKSyncEngine, because it seems that with CKSyncEngine I can control when to upload and download data and also monitor the progress.
My database schema (image below) has relationships - "1 to many" and "many to many" - so it's convenient to use SwiftData (and underlying CoreData).
Development environment: Xcode 16.1, macOS 15.1.1
Run-time configuration: iOS 18.1.1, macOS 15.1.1
My questions:
1-Is it possible to use SwiftData for local data storage and CKSyncEngine to sync this local data storage with iCloud?
2-If yes, is there any example code to implement this?
I've been studying the "CloudKit Samples: CKSyncEngine" demo app (https://github.com/apple/sample-cloudkit-sync-engine), but it uses a very primitive approach to local data storage by saving data to a JSON file on disk.
It would be very helpful to have the same demo app with SwiftData implementation!
3-Also, to make sure I don't run into problems later - is it okay to fire data upload (sendChanges) and download (fetchChanges) manually with CKSyncEngine and do it often? Are there any limits how often these functions can be called to not get "blocked" by the server?
4-If it's not possible to use SwiftData for local data storage and CKSyncEngine to sync this local data storage with iCloud, then what to use for local storage instead of SwiftData to sync it with iCloud using CKSyncEngine? Maybe use SwiftData with the new DataStore protocol instead of the underlying CoreData?
All information highly appreciated!
Thanks,
Martin
So the App Store got deleted or something after I got iOS 18 so then I asked Siri to open it for me and it said un supported URL
I have already built an app using SwiftData and now I want to introduce CloudKit features in it, what should I do? I'm totally new to this part. Thank you!
When a user first downloads my application they are prompted to sign into their apple account via a pop up.
I have not had this pop up previously, I believe the change occurred after iOS18.
I have functions that do a few things:
Retrieves userRecordID
Retrieves a userprofile(via userrecordid) from cloudkit.
Currently, I have an Unversioned Schema, and lightweight changes are automatically applied to the Models.
However, I'm planning to transition to a VersionedSchema, and I have a few questions:
Do I need to write all lightweight migrations in the Migration Plan? or is it automatically applied like the Unversioned Schema?
What happens if I do not create a lightweight migration? and just directly do lightweight changes to the latest VersionedSchema (example: Add a new property)?
I'm using SwiftData, and I'm using iCloud's CloudKit feature to back up my data.
The problem here is that once you start backing up your data, you can't erase it completely.
Even if the user adds 4 data and erases 4 again, I'm using about 2.5kb.
I don't know how the user using the app will accept this.
I'm trying to provide the user with the ability to erase data at once, what should I do??
Hey all -
Been building my app and all has been going well with successful builds through to test flight.
However, I have just added CKSharing support into the app and therefore into the entitlements to allow collaboration within the app.
As soon as I have added this, I can no longer build due to a signing certificate error stating my provisioning profile just not allow for CKSharing...
"Provisioning profile "iOS Team Provisioning Profile: com.MyApp" doesn't include the com.apple.developer.cksharing entitlement."
However, iCloud is enabled within my app profile, and all other cloudkit features have worked up until adding that specific entitlement.
Any help or guidance to get passed this would be greatly appreciated.
I've developed an app that allow me to send messages to all users by entering a record in Public database. On each users device, the app takes that Public record and creates a record in their Private database to track the Read and Deleted status.
It works flawlessly on the simulator and about 1/3 of the devices enrolled in my TestFlight. The other 2/3 are unable to write to their Private database. In fact, the CKContainer.default().privateCloudDatabase.save() operation causes the app to crash if I let it run.
I've looked at every Google link and I just can't figure out why this works for 1/3 of the users, but not the other 2/3. Incidentally, the 2/3 of the group that can't save to their Private database are also unable to save their Notification Subscription.
All devices are running iOS 18.0 or better iPhone 11 through 16 in testing pool. Each portion of the working/not working group are a mix of iPhone versions.
if !found && checkIcloudStatus() {
CKContainer.default().privateCloudDatabase.save(loadPrivateData(n: processedMessages[index].recordName)) { returnedRecord, returnedError in
print("Adding new message to Private and error is: \(String(describing: returnedError))")
DispatchQueue.main.async {
self.processedMessages[index].record = returnedRecord ?? CKRecord(recordType: "messages_private")
self.processedMessages[index].unRead = true
self.processedMessages[index].deleted = false
}
}
}
func loadPrivateData(n: String) -> CKRecord {
let record = CKRecord(recordType: "messages_private")
record["deleted"] = "false"
record["messageId"] = n
record["unRead"] = "true"
return record
}
I have opened the Push Notification and the Broadcast Capability at developer Capabilities, but when I call the api https://api-manage-broadcast.sandbox.push.apple.com:2195/1/apps/already change to my Identifiers/channels, I always got the "TopicMismatch".
Did I set something wrong somewhere?
Hello, I wanted to sync my Swift Data App with iCloud. I provided default values to all my models, made very relationship between my models optional. Then, at Signing and Capabilities, I finally added Background Modes (and checked Remote notifications) and iCloud (and checked CloudKit and added a container with my bundle id). Now I receive these errors every time I run my app on a device that is connect to iCloud
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _recoverFromError:withZoneIDs:forStore:inMonitor:](2620): <NSCloudKitMirroringDelegate: 0x302de80f0> - Failed to recover from error: CKErrorDomain:15
Recovery encountered the following error: (null):0
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _finishedRequest:withResult:](3582): Finished request: <NSCloudKitMirroringDelegateSetupRequest: 0x3031d4460> 53CB1DFC-E589-4945-8AF1-36126756110B with result: <NSCloudKitMirroringResult: 0x301c79320> storeIdentifier: 41F2B808-5C97-44B3-BC28-5534FEBCCF2C success: 0 madeChanges: 0 error: <CKError 0x301c98870: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 044262C6-5136-4989-823C-B0430F7B87DC; container ID = "iCloud.lu.yansoisson.blip-notes"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x301c7a9a0: "Server Rejected Request" (15/2000); op = 15C2EFE32CB459E1; uuid = 044262C6-5136-4989-823C-B0430F7B87DC>
}>
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest](3551): <NSCloudKitMirroringDelegate: 0x302de80f0>: Checking for pending requests.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest]_block_invoke(3567): <NSCloudKitMirroringDelegate: 0x302de80f0>: No more requests to execute.
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate recoverFromError:](2310): <NSCloudKitMirroringDelegate: 0x302de80f0> - Attempting recovery from error: <CKError 0x301c98870: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 044262C6-5136-4989-823C-B0430F7B87DC; container ID = "iCloud.lu.yansoisson.blip-notes"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x301c7a9a0: "Server Rejected Request" (15/2000); op = 15C2EFE32CB459E1; uuid = 044262C6-5136-4989-823C-B0430F7B87DC>
}>
Here's the debug message that appears first when I start the app
CoreData: debug: CoreData+CloudKit: -[PFCloudKitOptionsValidator validateOptions:andStoreOptions:error:](36): Validating options: <NSCloudKitMirroringDelegateOptions: 0x3023ec6e0> containerIdentifier:iCloud.lu.yansoisson.blip-notes databaseScope:Private ckAssetThresholdBytes:<null> operationMemoryThresholdBytes:<null> useEncryptedStorage:NO useDeviceToDeviceEncryption:NO automaticallyDownloadFileBackedFutures:NO automaticallyScheduleImportAndExportOperations:YES skipCloudKitSetup:NO preserveLegacyRecordMetadataBehavior:NO useDaemon:YES apsConnectionMachServiceName:<null> containerProvider:<PFCloudKitContainerProvider: 0x3010e62d0> storeMonitorProvider:<PFCloudKitStoreMonitorProvider: 0x3010e62e0> metricsClient:<PFCloudKitMetricsClient: 0x3010e62f0> metadataPurger:<PFCloudKitMetadataPurger: 0x3010e6300> scheduler:<null> notificationListener:<null> containerOptions:<null> defaultOperationConfiguration:<null> progressProvider:<NSPersistentCloudKitContainer: 0x300785440> test_useLegacySavePolicy:YES archivingUtilities:<PFCloudKitArchivingUtilities: 0x3010e6310> bypassSchedulerActivityForInitialImport:NO bypassDasdRateLimiting:NO activityVouchers:(
)
storeOptions: {
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
NSPersistentCloudKitContainerOptionsKey = "<NSPersistentCloudKitContainerOptions: 0x3036f0ea0>";
NSPersistentHistoryTrackingKey = 1;
NSPersistentStoreMirroringOptionsKey = {
NSPersistentStoreMirroringDelegateOptionKey = "<NSCloudKitMirroringDelegate: 0x302de80f0>";
};
NSPersistentStoreRemoteChangeNotificationOptionKey = 1;
}
CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate observeChangesForStore:inPersistentStoreCoordinator:](427): <NSCloudKitMirroringDelegate: 0x302de80f0>: Observing store: <NSSQLCore: 0x10214ca00> (URL: file:///var/mobile/Containers/Data/Application/780A6276-3BE4-458E-BD2D-EC304B123111/Library/Application%20Support/default.store)
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _setUpCloudKitIntegration:](589): <NSCloudKitMirroringDelegate: 0x302de80f0>: Successfully enqueued setup request: <NSCloudKitMirroringDelegateSetupRequest: 0x3031d4460> 53CB1DFC-E589-4945-8AF1-36126756110B
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest](3551): <NSCloudKitMirroringDelegate: 0x302de80f0>: Checking for pending requests.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest]_block_invoke(3564): <NSCloudKitMirroringDelegate: 0x302de80f0>: Executing: <NSCloudKitMirroringDelegateSetupRequest: 0x3031d4460> 53CB1DFC-E589-4945-8AF1-36126756110B
CoreData: warning: CoreData+CloudKit: -[PFCloudKitSetupAssistant _checkAccountStatus:]_block_invoke(342): Fetched account info for store 41F2B808-5C97-44B3-BC28-5534FEBCCF2C: <CKAccountInfo: 0x3007bbb80; accountStatus=Available, accountPartition=Prod, deviceToDeviceEncryptionAvailability=(account|device), hasValidCredentials=true, walrus=Enabled, needsToVerifyTerms=false, accountAccessAuthorization=Yes, validationCounter=545>
(null)
CoreData: warning: CoreData+CloudKit: -[PFCloudKitSetupAssistant _checkUserIdentity:]_block_invoke(1446): Fetched user recordID for store 41F2B808-5C97-44B3-BC28-5534FEBCCF2C: <CKRecordID: 0x3012ddbc0; recordName=_e002d189d325132b7dae12ad045e5d76, zoneID=_defaultZone:__defaultOwner__>
(null)
Does anyone know how to solve this issue since I have done everything exactly like mentioned in multiple tutorials and blogs?
Thanks
I want to clear all the data in the zone, but I can't delete it. Below is my code, no logs are printed when running.
static func clearData() {
let coordinator = shared.container.persistentStoreCoordinator
let fm = FileManager.default
for d in shared.container.persistentStoreDescriptions {
guard let url = d.url else { continue }
do {
if fm.fileExists(atPath: url.path()) {
try coordinator.destroyPersistentStore(at: url, type: .sqlite)
}
} catch {
logger.debug("Failed to delete db file, \(error)")
}
}
for description in shared.container.persistentStoreDescriptions {
guard let originalStoreURL = description.url else { continue }
let walFileURL = originalStoreURL.deletingPathExtension().appendingPathExtension("sqlite-wal")
let shmFileURL = originalStoreURL.deletingPathExtension().appendingPathExtension("sqlite-shm")
for url in [originalStoreURL, walFileURL, shmFileURL] {
do {
if fm.fileExists(atPath: url.path()) {
try fm.removeItem(at: url)
}
} catch {
logger.debug("Failed to delete db file, \(error)")
}
}
}
let container = CKContainer(identifier: appContainerID)
container.privateCloudDatabase.fetchAllRecordZones { zones, error in
if let error = error {
print("Error fetching zones: ")
} else if let zone = zones?.first, zone.zoneID.zoneName == "_defaultZone" {
PersistenceController.shared.container.purgeObjectsAndRecordsInZone(with: zone.zoneID, in: nil) { ckShare, error in
if let error = error {
print("Error purge zones: \(error)")
}
if ckShare == nil {
print("ckShare is nil")
}
}
}
}
}
I've been trying to setup a successful migration, but it keeps failing with this error:
NSCloudKitMirroringDelegate are not reusable and should have a lifecycle tied to a given instance of NSPersistentStore.
I can't find any information about this online. I added breakpoints throughout the code in willMigrate, and it originally failed on this line:
try? context.save()
I removed that, and it still failed. After I reload the app, it doesn't run the migration again and the app loads successfully. I figured since it crashed, it would keep trying, but I guess not. Here's how my migration is setup.
enum MigrationV1ToV2: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] {
[SchemaV1.self, SchemaV2.self]
}
static var stages: [MigrationStage] {
[stage]
}
static let stage = MigrationStage.custom(
fromVersion: SchemaV1.self,
toVersion: SchemaV2.self,
willMigrate: { context in
// Get cycles
let cycles = try? context.fetch(FetchDescriptor<SchemaV1.Cycle>())
if let cycles {
for cycle in cycles {
// Create new recurring objects based on what's in the cycle
for income in cycle.income {
let recurring = SchemaV2.Recurring(name: income.name, frequency: income.frequency, kind: .income)
recurring.addAmount(.init(date: cycle.startDate, amount: income.amount))
context.insert(recurring)
}
for expense in cycle.expenses {
let recurring = SchemaV2.Recurring(name: expense.name, frequency: expense.frequency, kind: .expense)
recurring.addAmount(.init(date: cycle.startDate, amount: expense.amount))
context.insert(recurring)
}
for savings in cycle.savings {
let recurring = SchemaV2.Recurring(name: savings.name, frequency: savings.frequency, kind: .savings)
recurring.addAmount(.init(date: cycle.startDate, amount: savings.amount))
context.insert(recurring)
}
for investment in cycle.investments {
let recurring = SchemaV2.Recurring(name: investment.name, frequency: investment.frequency, kind: .investment)
recurring.addAmount(.init(date: cycle.startDate, amount: investment.amount))
context.insert(recurring)
}
}
//try? context.save()
} else {
print("The cycles were not able to be fetched.")
}
},
didMigrate: { context in
// Get new recurring objects
let newRecurring = try? context.fetch(FetchDescriptor<SchemaV2.Recurring>())
if let newRecurring {
for recurring in newRecurring {
// Get all recurring with the same name and kind
let sameName = newRecurring.filter({ $0.name == recurring.name && $0.kind == recurring.kind })
// Add amount history to recurring object, and then remove matching
for match in sameName {
recurring.amountHistory.append(contentsOf: match.amountHistory)
context.delete(match)
}
}
//try? context.save()
} else {
print("The new recurring objects could not be fetched.")
}
}
)
}
Here's is my modelContainer in the app file. There is a fatal error occurring here that's crashing the app.
var sharedModelContainer: ModelContainer = {
let schema = Schema(versionedSchema: SchemaV2.self)
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(
for: schema,
migrationPlan: MigrationV1ToV2.self,
configurations: [modelConfiguration]
)
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
Does anyone have any suggestions for this?
EDIT:
I found this error in the console that may be relevant.
BUG IN CLIENT OF CLOUDKIT: Registering a handler for a CKScheduler activity identifier that has already been registered (com.apple.coredata.cloudkit.activity.export.8F7A1261-4324-40B4-B041-886DF36FBF0A).
CloudKit setup failed because it couldn't register a handler for the export activity. There is another instance of this persistent store actively syncing with CloudKit in this process.
And here is the fatal error
Fatal error: Could not create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer, _explanation: nil)
struct ModelContainerSetup {
static let shared = ModelContainerSetup()
private static let containerIdentifier = "iCloud.Journal"
func setupModelContainer() -> ModelContainer {
let schema = Schema([User.self])
let modelConfiguration = ModelConfiguration(
schema: schema,
isStoredInMemoryOnly: false,
cloudKitDatabase: .private(Self.containerIdentifier)
)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}
**Expected Behavior:
**
When CloudKit storage is full, the app should continue functioning with local storage
Data should persist locally even if cloud sync fails
Sync should resume when storage becomes available
**Actual Behavior:
**
ModelContainer initialization fails completely
Local data also stops getting saved
**Environment:
**
iOS 17.0+
SwiftData
Private CloudKit database
Ideal Behaviour:
When iCloud fails, the data should still be saved locally. I do not want to have two different containers so that I can maintain data consistency.