Hi,
does someone knows about the bug, that the NSPersistentCloudKitContainer doesn't return CKShares at the first time? Is this an intended behavior?
My current fix:
let container: NSPersistentCloudKitContainer = ....
// Fix begin
let managedObject = .... // Object which is in a share
let record = container.record(for: managedObject.objectID)
// Fix end
let shares = (try? container.fetchShares(in: nil)) ?? []
If I execute exactly the same code without the fix that I fetch the record first, then it returns 0 shares. With the fix it is currently 9 shares (the actual count of the shares).
Another fix:
let container: NSPersistentCloudKitContainer = ....
// Fix begin
let _ = try? container.fetchShares(in: nil)
Thread.sleep(forTimeInterval: 0.1)
// Fix end
let shares = (try? container.fetchShares(in: nil)) ?? []
For that fix it also returns at the second time the expected count of shares. But without the delay it returns also at the second time zero shares.
Anyone had the same problem and if so, how do you solve it correctly?
Thanks!
iCloud & Data
RSS for tagLearn how to integrate your app with iCloud and data frameworks for effective data storage
Post
Replies
Boosts
Views
Activity
We worked with SwiftData, and once CloudKit was integrated, the synchronization worked well. Even if I rerun the app, it works just as well.
However, when I delete the app and reinstall it, I get a Token Expired error and CloudKit doesn't work properly.
My code is organized like this
public lazy var modelContext: ModelContext = { ModelContext(modelContainer) }()
private lazy var modelContainer: ModelContainer = {
let schema = Schema([
Entity1.self,
Entity2.self,
Entity3.self,
])
let modelConfiguration = ModelConfiguration(
schema: schema,
groupContainer: .identifier("myGroupContainer"),
cloudKitDatabase: .automatic
)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
The error content is as follows
error: CoreData+CloudKit: -[PFCloudKitImportRecordsWorkItem fetchOperationFinishedWithError:completion:]_block_invoke(707): <PFCloudKitImporterZoneChangedWorkItem: 0x3022c0000 - <NSCloudKitMirroringImportRequest: 0x3036e7ac0> 1A7E53D4-E95B-423F-8887-66360F6D8865> {
(
"<CKRecordZoneID: 0x301bb1bf0; zoneName=com.apple.coredata.cloudkit.zone, ownerName=__defaultOwner__>"
)
} - Fetch finished with error:
<CKError 0x301bb5650: "Partial Failure" (2/1011); "Couldn't fetch some items when fetching changes"; uuid = 3F346302-C3EE-4F72-820C-988287C92C0A; container ID = "MyContainerID"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x301bb1830: "Change Token Expired" (21/2026); server message = "client knowledge differs from server knowledge"; op = 515034AC3ADC4348; uuid = 3F346302-C3EE-4F72-820C-988287C92C0A>
}>
error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:](1390): <PFCloudKitImporter: 0x3000a1240>: Import failed with error:
<CKError 0x301bb5650: "Partial Failure" (2/1011); "Couldn't fetch some items when fetching changes"; uuid = 3F346302-C3EE-4F72-820C-988287C92C0A; container ID = "MyContainerID"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x301bb1830: "Change Token Expired" (21/2026); server message = "client knowledge differs from server knowledge"; op = 515034AC3ADC4348; uuid = 3F346302-C3EE-4F72-820C-988287C92C0A>
}>
Forcing the ModelContainer to be reinitialized fixes the problem,
it's a problem to get this error in the first place,
the error doesn't even go to fatal for me, so I don't even know how to verify that it's happening.
Is there something I'm doing wrong, or do you have any good ideas for solving the same problem?
As of yesterday all queries my app makes to the CloudKit database, and requests via the CloudKit console result in 500 internal errors. We have made no changes to the database or app that could have caused this.
The status page for CloudKit database is green.
Here is a response from the CloudKit console:
{code: 500, message: "internal-error", reason: "Internal error", detailedMessage: undefined, requestUuid: "808955a2-e564-459e-ba9b-1101917ce1a4"}
While Query Record show error:
{
"code": 500,
"message": "internal-error",
"reason": "Internal error",
"requestUuid": "c10d378f-7133-4bea-a40d-d957f80f5de4"
}
Every record type in this container show same error.
But other containers of my apps works will.
Hello,
I want to build an app that will allow the user to entry some health related records and be synced with the HealthKit. Any record that is in the HealthKit is stored locally on the device.
I find it conceptually unsure if I should be storing the HealthKit records in the SwiftData to make the user records available across the iCloud synced devices.
Should I read the HealthKit record, make a copy of it (including it's ID) on my app's data in SwiftData?
How the syncing should be done the right way?
thanks.
We started to see some crashes in our iOS app a few seconds after launch with the following reason:
Exception Type: EXC_CRASH (SIGILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Termination Reason: SIGNAL 4 Illegal instruction: 4
when calling [NSPersistentContainer loadPersistentStoresWithCompletionHandler:].
I've looked through Understanding the exception types in a crash report page, but couldn't find this type there.
Any ideas what could it be?
Recently, I have been using SwiftData as a data persistence tool in my new SwiftUI app.
My app utilizes CLLocationManager for background location tracking to wake up the app and update SwiftData-related data. When the app is in the foreground or background, SwiftData's @Query can normally retrieve data. However, once the user manually terminates the app and it receives a location-based wake-up, SwiftData's @Query no longer retrieves data. I have looked through many resources and haven't found any similar documentation. I wonder if anyone can give me some suggestions?
I recently converted a Core Data app to use CloudKit. Before the conversion, the sqlite file was around 25MB. After the conversion, the file grew to over one gigabyte. I ran sqlite3_analyzer on the new file and found that a single table, ANSCKRECORDMETADATA, used 95% of the storage, 998MB.
Is this to be expected? I confess that the conversion was a bit bumpy. Maybe I did something to create a monstrosity.
If not expected, should I revert to the old Core Data file, create a new CloudKit container, and repeat the conversion.
My app uses Core Data to store an synchronise the data. It runs on iOS, iPadOS and now WatchOS. The records are stored in the private and shared CloudKit database.
Running the app in developer mode, syncing is fine for all devices.
But as soon as I switch to production mode using TestFlight, the Watch only syncs the data of the shared records, while iPad and iPhone still are syncing all records (private and shared) correctly.
I run out of ideas where to search for the reason of this problem. I use one module to setup the persistent store for iOS, iPadOs and WatchOS.
Any ideas are well come.
My App uses Core Data with Cloudkit when users purchased subscription (and uses only Core Data without subscription). My App should normally appear under 'Settings > [User Name] > iCloud > Apps using iCloud - Show All'; however, some users feedback that they my App cannot access iCloud (a message I displayed in my App when CKContainer.default().accountStatus is NOT available or FileManager.default.ubiquityIdentityToken == nil); and they do not see my App name under 'iCloud > Apps using iCloud - Show All'. From the screenshot that one user provided, only Apps from Apple are displayed under 'Apps using iCloud' and no third-party Apps are shown. Since the user can access to 'iCloud > Apple using iCloud', they have signed in to iCloud successfully. They have also tried to restart my App and restart the phone but the iCloud accessibility issue still remains.
How is it possible that iCloud is accessible only to Apps from Apple but not to third party Apps? What can developer do to resolve iCloud accessibility issue here?
I have v3 models in coredata (model: Event, Lecture), and make new model in v4 with swiftdata but model name, property is different (model: EventModel, LectureModel).
For migration, I add V3Schema, V4Schema and MigrationPlan.
enum V4Schema: VersionedSchema {
static var models: [any PersistentModel.Type] = [LectureModel.self, EventModel.self ]
static var versionIdentifier = Schema.Version(4, 0, 0)
}
enum V3Schema: VersionedSchema {
static var models: [any PersistentModel.Type] = [Event.self, Lecture.self]
static var versionIdentifier = Schema.Version(3, 5, 2)
}
enum ModelMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] = [V3Schema.self, V4Schema.self]
static var stages: [MigrationStage] = [migrateV3ToV4]
}
extension ModelMigrationPlan {
static let migrateV3ToV4 = MigrationStage.custom(fromVersion: V3Schema.self,
toVersion: V4Schema.self,
willMigrate: willMigrate,
didMigrate: { _ in Log.debug(message: "Migration Complete") })
}
private func willMigrate(context: ModelContext) throws {
try migrateLectures(context: context)
try migrateEvents(context: context)
try context.save()
}
private func migrateEventTypes(context: ModelContext) throws {
// create new v4 event model using v3 event model.
}
private func migrateLectures(context: ModelContext) throws {
// create new v4 lecture model using v3 lecture model.
}
static let release: ModelContainer = {
let v4Schema = Schema(V4Schema.models)
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "app group id")
let databaseURL = containerURL?.appending(path: "**.sqlite")
let configuration = ModelConfiguration("**",
schema: v4Schema,
url: databaseURL!,
cloudKitDatabase: .private("**"))
#if DEBUG
do {
try autoreleasepool {
let desc = NSPersistentStoreDescription(url: configuration.url)
let opts = NSPersistentCloudKitContainerOptions(containerIdentifier: configuration.cloudKitContainerIdentifier!)
desc.cloudKitContainerOptions = opts
desc.shouldAddStoreAsynchronously = false
if let model = NSManagedObjectModel.makeManagedObjectModel(for: V4Schema.models) {
let container = NSPersistentCloudKitContainer(name: "**", managedObjectModel: model)
container.persistentStoreDescriptions = [desc]
container.loadPersistentStores(completionHandler: { _, err in
if let err {
Log.error(message: "Store open failed: \(err.localizedDescription)")
}
})
try container.initializeCloudKitSchema()
Log.debug(message: "Initialize Cloudkit Schema")
if let store = container.persistentStoreCoordinator.persistentStores.first {
try container.persistentStoreCoordinator.remove(store)
}
}
}
} catch {
Log.error(message: "Failed: \(error.localizedDescription)")
}
#endif
return try! ModelContainer(for: v4Schema, migrationPlan: ModelMigrationPlan.self, configurations: configuration)
}()
But when I run, I got error message.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _scheduleAutomatedExportWithLabel:activity:completionHandler:]_block_invoke(3508): <NSCloudKitMirroringDelegate: 0x1036b1540> - Finished automatic export - ExportActivity - with result: <NSCloudKitMirroringResult: 0x1035da810> storeIdentifier: ***** success: 0 madeChanges: 0 error: Error Domain=NSCocoaErrorDomain Code=134407 "Request '*****' was cancelled because the store was removed from the coordinator." UserInfo={NSLocalizedFailureReason=Request '****' was cancelled because the store was removed from the coordinator.}
I don't know why store was removed from the coordinator.
Any have solutions?
I know if i change existing properties in a @Model it’s a migration. However if I add a new @Model class(es) that has no relationships to any existing is that still a migration or am i free to add?
if free to add, should i create a new model container or can I just add the new Model classes ?
I am new to Swift, and I am trying to get a grip on SwiftData, which SO FAR seems pretty straightforward EXCEPT relationships between tables. I come from a MYSQL, SQLITE3 background and I am used to “Primary Keys”, Inner and Outer Joins, One-to-One and One-to-Many relationships. Which SwiftData does not appear to do (I think).
I am following several reasonably good online tutorials on the subject, all of which gloss over how relationships work. The best one is a table for vegetables alongside a table of notes for each vegetable (A one-to-many relationship). The classes we set up for the schemas are as follows.
import Foundation
import SwiftData
@Model
class Vegetable {
var name: String
@Relationship(deleteRule: .cascade) var notes: [Note]?
init(name: String) {
self.name = name
}
}
@Model
class Note {
var text: String
var vegetable: Vegetable?
init(text: String) {
self.text = text
}
}
I can’t comprehend how they work. None of the tutorials I have watched explain it or explain it in a way I can understand.
In the “Vegetable” class, why is the field “notes” an array of type Notes?
Again in the “Vegetable” class does the field “notes” get stored in the database, if so what is stored?
In the “Note” Class it looks like the whole of the class “Vegetable” gets stored in the variable “vegetable”, which may or may not get stored in the database.
I'm trying to integrate the option to the player to save their data in the cloud, I integrate the CloudKit, change some stuff to make it work and build in Xcode to my phone.
But when I try to integrate the CloudSave, 50 unnasigned symbols jump,like this one:
Undefined symbol: _CKContainer_Default
I managed to fix them by updating the recommended settings for Xcode.
But then 4 more errors appear:
Sandbox: il2cpp(12538) deny(1) file-read-data /Users/Username/Test Apple Kit
2022/Build/Il2CppOutputProject/IL2CPP/build/deploy_arm64/il2cpp
So, don't let me build and I've looked everywhere but no one seems to had this same error
SwiftData includes support for CloudKit sync. However, I don't see any way to add conflict resolution behavior. For example, if different devices set different values for a field, or if a relationship is orphaned because of a deletion on another device, the application has to handle this somehow.
In Core Data (which SwiftData wraps), you can handle this with the conflict resolution system (docs) and classes like NSMergePolicy.
Is any of this accessible in SwiftData? If not, how do you deal with conflicts when syncing a SwiftData model with the cloud?
Just as you can right-click and force a file to 'Download Now', is there a way to force iCloud to prioritise a file to upload immediately?
When I go to Settings and tap on the account, choose iCloud>manage account storage and try to delete the storage associated with an app id developer mode, it doesn't give me the option to delete the data. I have tried using the CloudKit Console to delete the container data, but the entry for the app is still there. How do I delete it?
Hello,
Prior to iOS 17, it was possible to request user discoverability by calling ‚requestApplicationPermission‘. But now it is deprecated. How is the intended way to do this now? How this is for example handled in the Music App? I think this should be a similar approach.
Currently the only option for me seems to save the Email-Address (and maybe phone number) in the CloudKit public database, that other user can discover by this. But that the problem exists, that we need to fetch for changes at phone numbers and mail addresses that are linked to the iCloud account (because user might change anything). Is there a more elegant solution, than just checking the current email addresses and phone numbers at each start of the application (if that is even possible)?
For example the Music App has that Switch "Find my by Apple-ID" but I don't know how this is handled in the background.
Thanks!
Dear all,
I have the following two classes:
Stagioni:
import SwiftData
@Model
class Stagione {
@Attribute(.unique) var idStagione: String
var categoriaStagione: String
var miaSquadra: String
@Relationship(deleteRule: .cascade) var rosa: [Rosa]?
@Relationship(deleteRule: .cascade) var squadra: [Squadre]?
@Relationship(deleteRule: .cascade) var partita: [CalendarioPartite]?
init(idStagione: String, categoriaStagione: String, miaSquadra: String) {
self.idStagione = idStagione
self.categoriaStagione = categoriaStagione
self.miaSquadra = miaSquadra
}
}
CalendarioPartite:
import SwiftData
@Model
class CalendarioPartite {
var idGiornata: Int
var dataPartita: Date
var squadraCasa: String
var squadraTrasferta: String
var golCasa: Int
var golTrasferta: Int
var stagione: Stagione?
init(idGiornata: Int, dataPartita: Date, squadraCasa: String, squadraTrasferta: String, golCasa: Int, golTrasferta: Int) {
self.idGiornata = idGiornata
self.dataPartita = dataPartita
self.squadraCasa = squadraCasa
self.squadraTrasferta = squadraTrasferta
self.golCasa = golCasa
self.golTrasferta = golTrasferta
}
}
Now, I'd like to have a query which is showing in a view the list of partite depending on a selection of a specific Stagione.
I've tried with the following query, but I'm getting the following error: "Instance member 'selectedStagione' cannot be used on type 'CalendarioCampionatoView'; did you mean to use a value of this type instead?"
@Query(filter: #Predicate<CalendarioPartite> { $0.stagione == selectedStagione}) private var partite: [CalendarioPartite] = []
What I'm doing wrong?
Thanks,
A.
I unintentionally turned off iCloud Drive on iPhone.
iCloud deleted all my Desktop and Documents files
Then sync deleted all my Documents files from all other devices
iCloud.com website shows an empty folder.
I don’t have any files in the restorable section.
I don’t see any iCloud Archive folder created anywhere on my devices to restore.
The total amount of information stored was quite large, over 25 GB.
I turned back on the iCloud Drive feature, but no data shows up.
I have paid extended storage capacity. There is no way that with the push of a button, data that was stored on iCloud servers would be lost.
Nothing they say seems to help.
Can someone please advise - How to recover data?