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.

CloudKit Documentation

Posts under CloudKit tag

253 Posts
Sort by:
Post not yet marked as solved
0 Replies
95 Views
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.
Posted Last updated
.
Post marked as solved
1 Replies
88 Views
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
Posted
by Chris Tof.
Last updated
.
Post marked as solved
2 Replies
381 Views
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) )
Posted
by jonduenas.
Last updated
.
Post not yet marked as solved
0 Replies
78 Views
Hi Forum, I am wondering how I can filter the data retrieving from CloudKit with SwiftData and using the #Predicate macro? I always get this error message: Thread 1: Fatal error: Predicate does not support keypaths with multiple components Does someone know how to add two predicates and use CloudKit? Thanks in advance 😊
Posted
by 14slash12.
Last updated
.
Post not yet marked as solved
0 Replies
109 Views
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!
Posted
by EJ5608.
Last updated
.
Post marked as solved
1 Replies
169 Views
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!
Posted
by Hollycene.
Last updated
.
Post not yet marked as solved
0 Replies
121 Views
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?
Posted
by GoZoner.
Last updated
.
Post not yet marked as solved
1 Replies
182 Views
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.
Posted
by Bardi.
Last updated
.
Post marked as solved
6 Replies
986 Views
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.
Posted Last updated
.
Post not yet marked as solved
4 Replies
414 Views
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.
Posted Last updated
.
Post not yet marked as solved
1 Replies
178 Views
What interfaces do I use to propagate a CloudKit change in a shared zone to a notification/badge to all participants in the shared zone? Assume I have a 'League' that is the root object in a shared zone and that N Players are members of the league. One of the players, the 'organizer', schedules a 'Game' that is open to any of the players. When the organizer creates the game (in the league's shared zone) and it is mirrored in CloudKit, how can the other players see it (as a timely notification)? I already observe .NSPersistentStoreRemoteChange on NSPersistentStoreCoordinator and NSPersistentCloudKitContainer.eventChangedNotification on NSPersistentCloudKitContainer. Are these delivered in the background? Can/Should they generate a 'local/remote' notification for handling at the AppDelegate level? How? Do I need to use a CKDatabaseSubscription looking for CD_Game records directly? (I'd rather not; because then I'd have a potential race between the remote iCloud database(s) and the local CoreData)
Posted
by GoZoner.
Last updated
.
Post not yet marked as solved
0 Replies
118 Views
I am using the public cloud database to store my application data, this data is accessed by all users of the application, but at some point it is necessary for a user who did not create a respective data in the database to delete it, but from what I read in the documentation this is not possible, only with a permission. How do I allow a user to change or delete any data created by another user in the public cloud database?
Posted
by useravsr.
Last updated
.
Post not yet marked as solved
2 Replies
200 Views
Young developer (old man though) need some advice/guidance on how to fault find iCloud issues. A new App, pretty much started with iCloud setup, and I believe I have fulfilled all the necessary prerequisites. I have built other Apps that have worked find on iCloud, but this one simply refuses to work. Error messages from the Console log file as follows: =====>> error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1223): <NSCloudKitMirroringDelegate: 0x2812901e0>: Failed to set up CloudKit integration for store: <NSSQLCore: 0x15bd05ee0> (URL: file:///var/mobile/Containers/Data/Application/EB138C06-5CE0-4FD2-BDCB-3087AF075ED6/Library/Application%20Support/MyShoppingLists.store) <CKError 0x2823edf80: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 838326A8-25E4-4239-8FBF-F2604F1DEC3D; partial errors: { com.apple.coredata.cloudkit.zone:defaultOwner = <CKError 0x2823ed230: "Server Rejected Request" (15/2001); "Request failed with http status code 500"; uuid = 838326A8-25E4-4239-8FBF-F2604F1DEC3D> }> <<=====>> error: CoreData+CloudKit: NSCloudKitMirroringDelegate recoverFromError:](2303): <NSCloudKitMirroringDelegate: 0x2812901e0> - Attempting recovery from error: <CKError 0x2823edf80: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 838326A8-25E4-4239-8FBF-F2604F1DEC3D; partial errors: { com.apple.coredata.cloudkit.zone:defaultOwner = <CKError 0x2823ed230: "Server Rejected Request" (15/2001); "Request failed with http status code 500"; uuid = 838326A8-25E4-4239-8FBF-F2604F1DEC3D> }> <<=====>> error: CoreData+CloudKit: NSCloudKitMirroringDelegate _recoverFromError:withZoneIDs:forStore:inMonitor:](2604): <NSCloudKitMirroringDelegate: 0x2812901e0> - Failed to recover from error: CKErrorDomain:15 Recovery encountered the following error: (null):0 <<===== Thanks in advance for any suggestions...
Posted Last updated
.
Post not yet marked as solved
2 Replies
202 Views
Hey everyone, I'm trying to get the user's name to display in a welcome screen, but unfortunatelly no success so far. For that, I'm using CKContainer.default().shareParticipant(forUserRecordID: recordID).userIdentity.nameComponents, but the returned nameComponents are empty, despite receiving no error and accountStatus of .available. Here's my code: struct Helper { static func getUserInformation() async throws -> Models.UserInfo { let container = CKContainer.default() let accountStatus = try! await container.accountStatus() var accountStatusDescription = "" switch accountStatus { case .couldNotDetermine: accountStatusDescription = "couldNotDetermine" case .available: accountStatusDescription = "available" case .restricted: accountStatusDescription = "restricted" case .noAccount: accountStatusDescription = "noAccount" case .temporarilyUnavailable: accountStatusDescription = "temporarilyUnavailable" @unknown default: accountStatusDescription = "default" } print("[Helper] CKContainer accountStatus: \(accountStatusDescription) ") // Prints "[Helper] CKContainer accountStatus: available" do { let recordID = try await container.userRecordID() let id = recordID.recordName let participant = try await container.shareParticipant(forUserRecordID: recordID) guard let nameComponents = participant.userIdentity.nameComponents else { throw Models.ServiceError.userIdentityUnknownName } print("[Helper] CKShare.Participant nameComponents \(nameComponents)") // Prints "[Helper] CKShare.Participant nameComponents - " print("[Helper] CKShare nameComponents.givenName \(String(describing: nameComponents.givenName))") print("[Helper] CKShare nameComponents.nickname \(String(describing: nameComponents.nickname))") print("[Helper] CKShare nameComponents.familyName \(String(describing: nameComponents.familyName))") print("[Helper] CKShare nameComponents.namePrefix \(String(describing: nameComponents.namePrefix))") print("[Helper] CKShare nameComponents.nameSuffix \(String(describing: nameComponents.nameSuffix))") print("[Helper] CKShare nameComponents.middleName \(String(describing: nameComponents.middleName))") let name = PersonNameComponentsFormatter().string(from: nameComponents) return Models.UserInfo( id: id, name: name ) } catch { throw error } } } Other than that, this project is using CloudKit for persistence through SwiftData and everything seems to be duly setup and working fine. Any idea of what I might be missing? Any user permissions required? As far as I understood, from iOS 17 on and using this code, no permissions are required anymore but I may be wrong. Any hint / help would be much appreciated! Cheers, Jorge
Posted
by j_oneill.
Last updated
.
Post not yet marked as solved
3 Replies
382 Views
I enabled Advanced Data Protection for my developer account, and this (understandably) broke access to my private records in CloudKit Console. I disabled Advanced Data Protection but CloudKit Console still cannot connect. In the database popup the "Click here to retry..." option always fails silently. Does anyone know a workaround?
Posted
by jhokit.
Last updated
.
Post not yet marked as solved
0 Replies
136 Views
I implemented to my app iCloud backup and restore services. Basically App uploads it's document directory files to iCloud using NSURL containerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; and [fileManager copyItemAtURL:fileURL toURL:destinationURL error:&error]; and everything has been OK to upload files. By checking my iCloud account, it has taken the space needed to store those files. However, when I changed my decice, I'm unable to get those files back. At first, files had .icloud extra extension added, but now the function just reports only 5 files from few hunder. The function used to get backup files is: `- (NSArray) getBackupFiles { NSError *error; NSURL *containerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; if (!containerURL) return nil; // NSArray *keysArray = [[NSArray alloc] initWithObjects: nil]; NSArray *resultsArray = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:containerURL includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:&error]; if (error) { [self myAlertView:error.localizedDescription]; return nil; } else return resultsArray; } Any ideas, what went wrong?`
Posted Last updated
.
Post not yet marked as solved
2 Replies
154 Views
I'm having some trouble with the following function from the CKSyncEngineDelegate protocol. func nextRecordZoneChangeBatch(_ context: CKSyncEngine.SendChangesContext, syncEngine: CKSyncEngine) async -> CKSyncEngine.RecordZoneChangeBatch? { The sample code from the documentation is func nextRecordZoneChangeBatch( _ context: CKSyncEngine.SendChangesContext, syncEngine: CKSyncEngine ) async -> CKSyncEngine.RecordZoneChangeBatch? { // Get the pending record changes and filter by the context's scope. let pendingChanges = syncEngine.state.pendingRecordZoneChanges .filter { context.options.zoneIDs.contains($0) } // Return a change batch that contains the corresponding materialized records. return await CKSyncEngine.RecordZoneChangeBatch( pendingChanges: pendingChanges) { self.recordFor(id: $0) } } init?(pendingChanges: [CKSyncEngine.PendingRecordZoneChange], recordProvider: (CKRecord.ID) -> (CKRecord?)) works fine for the sample app which only has one record type, but it seems incredible inefficient for my app which has a dozen different record types. The recordProvider gives you a CKRecord.ID, but not the CKRecord.RecordType. Searching each record type for a matching ID seems very inefficient. Doesn't the CKSyncEngine.PendingRecordZoneChange contain an array of CKRecords, not just CKRecord.IDs? According to the documentation CKSyncEngine.RecordZoneChangeBatch has a recordsToSave property, but Xcode reports 'CKSyncEngine.PendingRecordZoneChange' has no member 'recordsToSave' I'm looking for someway to get the CKRecords from syncEngine.state.pendingRecordZoneChanges.
Posted
by adamek.
Last updated
.
Post not yet marked as solved
1 Replies
248 Views
I get this error even though everything is turned on, how can I solve it? It works on IOS but I get this error on VisionOS CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _recoverFromPartialError:forStore:inMonitor:]_block_invoke(2726): <NSCloudKitMirroringDelegate: 0x600003b0c700>: Found unknown error as part of a partial failure: <CKError 0x600000cce460: "Permission Failure" (10/2007); server message = "Invalid bundle ID for container"; op = 7FE8CD52A7B2E8FC; uuid = D8D1F2C9-2C01-45B2-BECC-270CA5520D55; container ID = "iCloud.Multitools"> let previewContainer:ModelContainer = { do { let config = ModelConfiguration(cloudKitDatabase: .private("iCloud.Multitools")) let container = try ModelContainer(for: NoteModel.self, configurations: config) return container } catch { fatalError("Error to create container") } }()
Posted
by OVRIDOO.
Last updated
.
Post not yet marked as solved
0 Replies
214 Views
I want to make icloud backup using SwiftData in VisionOS and I need to use SwiftData first but I get the following error even though I do the following steps I followed the steps below I created a Model import Foundation import SwiftData @Model class NoteModel { @Attribute(.unique) var id: UUID var date:Date var title:String var text:String init(id: UUID = UUID(), date: Date, title: String, text: String) { self.id = id self.date = date self.title = title self.text = text } } I added modelContainer WindowGroup(content: { NoteView() }) .modelContainer(for: [NoteModel.self]) And I'm making inserts to test import SwiftUI import SwiftData struct NoteView: View { @Environment(\.modelContext) private var context var body: some View { Button(action: { // new Note let note = NoteModel(date: Date(), title: "New Note", text: "") context.insert(note) }, label: { Image(systemName: "note.text.badge.plus") .font(.system(size: 24)) .frame(width: 30, height: 30) .padding(12) .background( RoundedRectangle(cornerRadius: 50) .foregroundStyle(.black.opacity(0.2)) ) }) .buttonStyle(.plain) .hoverEffectDisabled(true) } } #Preview { NoteView().modelContainer(for: [NoteModel.self]) }
Posted
by OVRIDOO.
Last updated
.
Post marked as solved
1 Replies
158 Views
I remember long time ago I could click on a button in Xcode to launch a Web page to manage iCloud data. But now I cannot find the button.
Posted
by imneo.
Last updated
.