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

249 Posts
Sort by:
Post not yet marked as solved
0 Replies
224 Views
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
Posted
by
Post not yet marked as solved
2 Replies
237 Views
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?
Posted
by
Post not yet marked as solved
0 Replies
213 Views
My app is currently on the app store for IOS, iPadOS and MacOS. I have created a version for Apple TV but cannot get it to save to iCloud. Is there anyone who can help me get my app to save to iCloud for the Apple TV?
Posted
by
Post not yet marked as solved
1 Replies
229 Views
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.
Posted
by
Post not yet marked as solved
2 Replies
240 Views
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.
Posted
by
Post marked as solved
1 Replies
410 Views
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 :)
Posted
by
Post not yet marked as solved
0 Replies
288 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
by
Post marked as solved
1 Replies
364 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
Post not yet marked as solved
0 Replies
192 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
Post not yet marked as solved
0 Replies
216 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
Post marked as solved
1 Replies
321 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
Post not yet marked as solved
0 Replies
242 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
Post not yet marked as solved
1 Replies
331 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
Post not yet marked as solved
0 Replies
219 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
Post not yet marked as solved
2 Replies
331 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
by
Post not yet marked as solved
1 Replies
340 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
Post not yet marked as solved
2 Replies
305 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
Post not yet marked as solved
0 Replies
192 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
by
Post not yet marked as solved
2 Replies
231 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
Post not yet marked as solved
1 Replies
385 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