CloudKit

RSS for tag

Store 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

CloudKit - Cannot create or modify field 'CD_nameFirstChar' in record 'CD_Charts' in production schema
Some of my users are reporting an inability to sync via CloudKit between devices. I have not seen it on any of my devices, but one user got me some console logs that are showing the following error: <CKError 0x600000a0f840: "Partial Failure" (2/1011); "Failed to modify some records"; uuid = EDC7B3E3-02F8-43B7-83B6-22D17EF0442A; container ID = "iCloud.cribaudo.iphemeris"; partial errors: { C611E11F-3DC0-484C-8FC1-23473062D9D0:(com.apple.coredata.cloudkit.zone:defaultOwner) = <CKError 0x600000a04660: "Invalid Arguments" (12/2006); server message = "Cannot create or modify field 'CD_nameFirstChar' in record 'CD_Charts' in production schema"; op = D83EF1F7DD772042; uuid = EDC7B3E3-02F8-43B7-83B6-22D17EF0442A> I do not understand this: The field CD_nameFirstChar was added to the data model in the version 15. Automatic Migration is enabled. The CloudKit Console says the Private Database Container being used by my App is deployed to production. The entity CD_Charts (I only have one) that is deployed to production shows that field as present (CD_nameFirstChar). Why would this user be getting this error? As far as I can see they are running a version where migration to Model 15 should have been triggered at some point in the past. If somehow something went wrong with their migration, how would I fix it? Any thoughts / ideas are appreciated. One thing I should add is that the migration from Model 14 to 15 was not lightweight. I did use: @interface ModelMigration14to15 : NSEntityMigrationPolicy -(NSString *)nameFirstChar:(NSString *)name; @end And I used a MapModel14to15 which used the above function to set the value of nameFirstChar. The Value Expression for that attribute is: FUNCTION($entityPolicy,` "nameFirstChar:" , $source.name) from the above mentioned NSEntityMigrationPolicy class. This worked ok on all my devices and apparently on some user devices. This issues seems to effect only a small subset of my users but not all? So I am at a loss to understand why this would happen or how to fix it.
2
0
408
Apr ’24
CKQueryOperation in private database produces 500 errors from server and in CloudKit Console
I've been scratching my head on this one. Out of the blue, part of my 'synchronization' mechanism that copies 'favorites' from device to device has stopped working. A user can save a favorite location and it will propagate to all of their other devices, or repopulate after an uninstall and reinstall. My code in the space hasn't changed for months and I haven't made any schema changes to this type either. Last night I noticed the process wasn't working anymore. My CKQueryOperation result completion is returning this error: &lt;CKError 0x2818a16b0: "Server Rejected Request" (15/2001); "Request failed with http status code 500"; uuid = 2CA523A6-8F39-4538-98AF-E9B7D6CACF73&gt; What is telling to me is that the CloudKit Console also fails with an internal error when I try to query this type in MY private database for two different accounts. I can query another type in the private database but this one won't work for two of the Apple ID's I have tried. Also interesting, if I query this type in the PUBLIC database, even though this type is only saved to the private database, that operation succeeds just fine. I don't want to burn a DTS ticket for a server issue. FB13543186 - CloudKit: Receiving 500 when performing a query operation on the private database CloudKit status page is green on the developer site as of this morning.
3
0
616
Apr ’24
CKSyncEngine - Are the "change batches" we send to iCloud guaranteed to be identical to the batches iCloud sends back to other devices?
Hey, I'm currently working on adding CloudKit support to the GRDB SQLite database in my app. CKSyncEngine, though still a bit tricky to wrap your head around, is amazing! I have most of the basic setup implemented and some very easy cases already work, which is really exciting! However, I do have some questions regarding data consistency across devices. I'm not sure though, that these questions are actually "correct" to ask. Maybe my entire approach is inherently flawed. Say we add two records to the pending changes of the sync engine: // I'm simplifying CKRecord.ID to be a String here syncEngine.state.add(pendingRecordZoneChanges: [.saveRecord("1"), .saveRecord("2")] Let's also say that both records are tightly connected. For example, they could be in a one-to-one relationship and must always be added to the database together because the app relies on the existence of either none or both. After that call, at some later point, the system will call the sync engine's delegate nextRecordZoneChangeBatch(_:syncEngine:) for us to batch the changes together to send to iCloud. First question: Can we guarantee that records "1" and "2" always land in the exact same batch, and are never separated? Looking at the example code, there are two line that worry me a bit: // (Sample project: `SyncedDatabase.swift, lines 132-133`) let scope = context.options.scope let changes = syncEngine.state.pendingRecordZoneChanges.filter { scope.contains($0) } The scope could lead to one of the two records being filtered out. However, my assumption is that the scope will always be .all when the system calls it from an automatically managed schedule, and only differs when you manually specify a different value through calling syncEngine.sendChanges(_:). Is that correct? Now back to the example. Say we successfully batched records "1" and "2" together and the changes have been sent to iCloud. Awesome! What happens next? Other connected devices will, at some point, fetch those changes and apply them to their respective local databases. Second question: Can we guarantee that iCloud sends the exact same batches from earlier to other devices and does not create new batches from all the changes? I'm worried that iCloud might take all stored changes and "re-batch" them for whatever reason (efficiency, for example). Because that could cause records "1" and "2" to be separated into different batches. A second device could end up receiving "1" and, for at least some period of time, will not receive "2", which would be an "illegal" state of the data. I'd appreciate any help or clarification on this :) Thanks a lot!
2
0
328
Apr ’24
What Apple user account do you use when testing CloudKit in Xcode
I currently have a production app that uses CloudKit I always struggle with testing the data within the development container and I was wondering if someone could share their current workflow. What is your current workflow when testing apps that use CloudKit, do you use your regular Apple User account for testing, or you use separate account? My concern is because I use my production app on a daily basis using my regular Apple user account, so I would like to keep the production iCloud data intact. In other words, I have my app on my phone with real data and now I need to test the app because there are some CloudKit syncing issues so I have the following questions. Can I connect my phone with production data to Xcode and use my regular Apple account for testing purposes? Will I be able to see the testing data in the CloudKit console? Will the production data merge with the testing data? I actually created a second Apple account thinking that I could use it for testing but logging off and logging back on to iCloud in your iPhone it's a pain, is this really what needs to be done? Any ideas would be greatly appreciated. Thanks
0
0
395
Apr ’24
Questions about isExcludedFromBackup option and device migration
Questions about isExcludedFromBackup option and device migration I posted a similar question a year ago, but I still haven't found a solution that I like, so I'm leaving this question. If anyone knows how, please let me know. In our app, we set the isExcludedFromBackup option to true so that files currently in the Documents path are not backed up to iCloud. In the current situation, I am just curious as to whether the files of our app can be backed up in the two situations below. (with isExcludedFromBackup option set to true ) Migrate iPhone to new iPhone Backup and restore the entire device to iTunes If you set the isExcludedFromBackup option to true in the file, iCloud backup will not be possible, and the app's internal files will not be copied even in the two situations mentioned above. Is there an option or method in the app's internal code to prevent automatic backup only to iCloud and allow files to be copied or synchronized in the above two situations?
2
0
383
Apr ’24
SwiftData deleteRules & uniqueness
Hello everyone, How do I need to handle the delete with the relationship deny? When I delete a model that still has a reference to another model, it deletes it from the UI. But when I re-run the simulator, it's back again. Does someone have a hint for me? How is it possible to ensure the uniqueness of the entries? Because I saw that the Attribute unique can't be used with CloudKit.
1
0
382
Apr ’24
Is it possible to fix slow CKAsset loading on Cloudkit?
I am trying to create a specialised photo sharing social network using CloudKit alone. The app will never need to be non iOS, so on the surface Cloudkit has seemed like a perfect backend. However, I've found at random but semi frequent times, the loading of CKAssets from records can be very slow. For example, at normal times, all of the assets can load in a second or less. However at other times, it can take from 5 to 15 seconds. This is on a public database using a fetch operation where I already have the record IDs. Here is my code that performs that: mainDatabase.fetch(withRecordIDs: recordIDS, desiredKeys: ["image"]) { results in var recordsToReturn: [CKRecord] = [] switch results { case .success(let success): for (_, result) in success { switch result { case .success(let record): // If the result is success, append the record to the successfulRecords array recordsToReturn.append(record) break case .failure(_): break } } completion(.success(recordsToReturn)) case .failure(let failure): completion(.failure(failure)) } } } Of note, I have also tried using a database operation at set the qualityOfService to userInitiated, which has had the same noticeable load times. I have also tested this on different devices, on different networks (both cellular & different WiFi connections) and found also the same noticeable load times at random occurrences. Therefore, what I am trying to find out: Is this an expected behaviour from using CloudKit? Is there a much better way to load CKAssets that would drastically help this load time issue? Is CloudKit even a viable option for this kind of app, or is it not designed for this type of app? What alternative approaches could be taken? (Eg. store assets in AWS...) Would truly appreciate any feedback & guidance on this issue.
2
0
325
Apr ’24
SwiftData not syncing with iCloud
Hello everyone, I followed this (https://www.hackingwithswift.com/quick-start/swiftdata/how-to-sync-swiftdata-with-icloud) guide from Paul Hudson on how to sync swiftdata with iCloud. I tried it on my device directly and it worked exactly as I would expect. Now I tried the same version of the app on another device installed through TestFlight external tester group. It no longer works. When deleting the app, the alert reads "Deleting this app will also delete its data, but any documents or data will be stored in iCloud will not be deleted" so the app should have said something in iCloud. When looking in Settings -> Your Name -> iCloud -> Manage Account Storage, on the working device I can see around 300 KB saved in iCloud, on the other device my app is not listed. Both have a fast and working internet connection, almost fully charged, low data mode turned off, running 17.4.1, Background modes enabled, Mobile data enabled, more than enough unused iCloud storage and plenty of time to sync. I was streaming the logs from the Cloudkit dashboard but nothing appeared there. The data saved neither syncs to another device of the same apple id nor reappears after app removal. The model Container is initialized without any configuration, the only relationship is optional and every value has a default value. There is A LOT of log noise when launching the app and I am unable to get any meaningful information from that. I can only get the log from the device where it is working as expected. I have triple checked that it is exactly the same app version and no debug conditions anywhere. I have absolutely no idea what is causing this. Thanks for any help :)
1
0
947
Mar ’24
How to clear locally cached SwiftData database on macOS
I am developing a SwiftData application using CloudKit. I have been playing with the app for a while and populated the database. Recently I decided to change the type of an attribute. So I reseted the scheme in CloudKit Console to the production one, which actually is empty for now, so I restart from scratch. Unfortunatly, the locally cached database on my Mac is using the old schema and my app fails loading the ModelContainer because of the type incompatibilities. I would like to delete the locally cached database but I haven't a clue of where it can be. I do not want to go through a migration plan for that. Does someone know where can I find it ? Chris tof
1
0
914
Mar ’24
SwiftData with CloudKit failing to migrate schema
My app has been in the App Store a few months. In that time I've added a few updates to my SwiftData schema using a MigrationPlan, and things were seemingly going ok. But then I decided to add CloudKit syncing. I needed to modify my models to be compatible. So, I added another migration stage for it, changed the properties as needed (making things optional or adding default values, etc.). In my tests, everything seemed to work smoothly updating from the previous version to the new version with CloudKit. So I released it to my users. But, that's when I started to see the crashes and error reports come in. I think I've narrowed it down to when users update from older versions of the app. I was finally able to reproduce this on my end, and Core Data is throwing an error when loading the ModelContainer saying "CloudKit integration requires that all attributes be optional, or have a default value set." Even though I did this in the latest schema. It’s like it’s trying to load CloudKit before performing the schema migration, and since it can’t, it just fails and won’t load anything. I’m kinda at a loss how to recover from this for these users other than tell them to delete their app and restart, but obviously they’ll lose their data that way. The only other idea I have is to setup some older builds on TestFlight and direct them to update to those first, then update to the newest production version and hope that solves it. Any other ideas? And what can I do to prevent this for future users who maybe reinstall the app from an older version too? There's nothing special about my code for loading the ModelContainer. Just a basic: let container = try ModelContainer( for: Foo.self, Bar.self, migrationPlan: SchemaMigration.self, configurations: ModelConfiguration(cloudKitDatabase: .automatic) )
4
3
1.2k
Mar ’24
CloudKit private database & developer access to user data
My app does not knowingly capture or retain user data in any form, but I wanted to make sure that I don’t inadvertently have access to user data via CloudKit. I’m reaching out to confirm this. Here’s the basic structure of the app - users can enter information which is then retained for their own use. I’m using SwiftData. @Model data is saved in a CloudKit container, which permits data syncing across iOS devices. I’ve never written any code to make the container database I’m using for the app (or zones within it) anything other than private, so I think (??) by default the data is stored privately. Data syncing does work and my icloud.developer.apple.com dashboard shows a private database subscription but no public or shared subscriptions. My understanding of this design has been that the user’s data was stored in their personal, private iCloud account and I did NOT have access to it (nor do I need or want to have access). However, then I watched this WWDC 2018 video on GDPR compliance (https://developer.apple.com/videos/play/tech-talks/703/), in which Michael Ford presents code that provides “visibility into the data that is saved in CloudKit for the user”, including the private database. This sounds to me like a developer might actually be able to access a user’s private database data. Have I misinterpreted this WWDC 2018 presentation, has a developer’s access to user data in a private database changed since 2018, or do I actually have access to user data via my reliance on CloudKit to save user data? Many thanks for your help!
0
0
296
Mar ’24
What is the proper time to deploy CloudKit Schema to Production?
The Statement I have a SwiftUI app that uses CoreData and iCloud with NSPersistentCloudKitContainer prepared for beta testing via TestFlight. The app utilizes iCloud solely as a private database for user data across different devices. The app doesn't use any public or shared database. According to Apple's guidelines, deploying the development schema to production is necessary before submitting to the App Store: Before you publish your app, you must deploy the development schema to the production environment to copy over its record types, fields, and indexes. I am aware that once deployed to production, it's impossible to delete or modify any types or fields: To prevent conflicts, you can’t delete record types or fields that are already in production. Every time you deploy the development schema, its additive changes merge into the production schema. The Questions: When is the appropriate time to deploy the schema to production? Should it be done before beta testing via TestFlight, or is it sufficient to deploy it just before releasing the app on the App Store after beta testing? If the schema needs to be deployed before beta testing, does that mean I won't be able to reset the schema if testers discover critical bugs related to the data model, and I'll be compelled to delete or modify any types or fields? Thank you in advance for any responses!
1
0
468
Mar ’24
CoreData + CloudKit: Transient Properties Across Configurations
I've defined 'public' and 'private' configurations in CoreData and configured the 'public' configuration to be handled in the CloudKit publicDB. The two configurations contain disjoint sets of NSManagedObject entity types. Some of the entities in the private configuration reference an entity in the public configuration using a UUID; thereby avoiding cross-configuration CoreData relationships. Avoiding this is a requirement of CoreData + CloudKit. Now, since the UUID is meant to point to an object, in the awakeFromFetch() method I decided to fill in a transient property. No go. Even for a transient property there cannot be a cross-configuration relationship. Why? Is there a way to avoid this constraint? The cost of not having a transient property is to do a fetch of the object based on the UUID every time it is needed. Is this something that one should never worry about?
0
0
322
Mar ’24
SwiftData synced to iCloud with one-to-many relationship between 2 models results in a crash when each model contains a reference to the other
I’m having an issue when two of my SwiftData models have a one-to-many relationship and I have them synced via CloudKit. To be clear, I’ve met all of the requirements to make it iCloud friendly and sync to work. I followed this https://www.hackingwithswift.com/quick-start/swiftdata/how-to-sync-swiftdata-with-icloud, and can confirm I’ve done it correctly because initially I was seeing this crash on startup when I had not: Thread 1: Fatal error: Could not create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer) This is to say, the problem may be iCloud related but it’s not due to a wrong model setup. Speaking of which, these are models: @Model class Film { var name: String = "" var releaseYear: Int = 0 var director: Director? = nil init(name: String, releaseYear: Int, director: Director) { self.name = name self.releaseYear = releaseYear self.director = director } } @Model class Director { var name: String = "" @Relationship(deleteRule: .cascade, inverse: \Film.director) var films: [Film]? = [] init(name: String, films: [Film]) { self.name = name self.films = films } } I’ve set the delete rule for the relationship between Film and Director to be cascading because you can’t have a film without a director (to be clear, even when set as nullify, it doesn’t make a difference) And this is the @main App definition: @main struct mvpApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Film.self, Director.self ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() } } And this is the dummy ContentView: struct ContentView: View { var body: some View { EmptyView() .onAppear { let newDirector = Director(name: "Martin Scorcese", films: []) let film = Film(name: "The Wolf of Wall Street", releaseYear: 2019, director: newDirector) newDirector.films!.append(film) } } } I create a Director with no films assigned. I then create a Film, and the append it to the Director’s [Film] collection. The last step however causes a crash consistently: There is a workaround that involves removing this line from the Film init(): self.director = director // comment this out so it’s not set in a Film’s init() When I do this, I can append the (Director-less) Film to the Director’s [Film] collection. Am I misunderstanding how these relationships should work in SwiftData/CloudKit? It doesn’t make any sense to me that when two models are paired together that only one of them has a reference to the relationship, and the other has no knowledge of the link. The above is a minimum reproducible example (and not my actual application). In my application, I basically compromised with the workaround that initially appears to be without consequence, but I have begun to notice crashes happening semi-regularly when deleting models that I suspect must be linked to setting the foundations incorrectly.
1
0
561
Mar ’24
Manually define a CKRecord ID for a given NSManagedObject instance
I have an app that is already running with CoreData, and I want to allow the users to upload their data to iCloud so, in the case they need to delete their apps or change devices, they don't lose it. Every time the app is opened, there is a synchronization that happens between CoreData and a JSON file fixture, in order to fill the app with its base values (creating NSManagedObject instances from the aforementioned fixture). Before the iCloud sync, the CoreData model had some constraints for different entities, to enforce uniqueness, but these had to be stripped since CloudKit doesn't support them. Most of these constraints were basically ids that came from the JSON and represent an item in our Firebase database. Given that, I want to make the underlying CKRecord.id the same as these ids, so I can avoid the situation where, if a person open the app in a second device, the fixture data is repeated, since the fixture runs before the sync with the iCloud happens. Is that possible? Any help would be appreciated.
6
0
1.3k
Mar ’24
Private database: failed to access iCloud data please signin again.
When I logged into my cloudkit console to inspect the database for some debugging work I couldn't access the private database. It keeps saying "failed to access iCloud data, please signi n again". No matter how many times I sign in again, whether with password or passwordless key it keeps saying the same thing. It says that message when I click on Public database, and private and shared databases are below it. I only noticed this a couple of days ago. It's done this in the past, but I eventually got back into the database but I don't know what changed to make it work.
7
5
821
Mar ’24