iCloud & Data

RSS for tag

Learn how to integrate your app with iCloud and data frameworks for effective data storage

CloudKit Documentation

Posts under iCloud & Data subtopic

Post

Replies

Boosts

Views

Activity

How to get a real time and date (not device time) for query?
I need to know the current date to query CloudKit data with it, like: let predicate = NSPredicate(format: "publishedAt <= %@", currentDateAndTime) I don't need high precision, even +/- a few minutes is fine, but I can't rely on device's time since the user can manually change it. Researching this myself I see that the most reliable method is to get the date from the server. There are NTP servers, but accessing them requires additional libraries which adds complexity. TrueTime (last updated 6 years ago) and Kronos (updated like once a year) seem outdated, given how much Swift has changed in the past years. I can make an HTTP request to a website like Google or Apple and read the current time from its headers. But I don't know if this method is reliable. I know I can create a dummy record in CloudKit, update it, and read its modificationDate. But it feels hacky. Maybe there is another way to fetch the current date directly from CloudKit? It feels like it should be easy and there is a straightforward solution, but I just can't find it.
1
0
600
Jan ’25
What is going on with transformable
Hi, I keep trying to use transformable to store an array of strings with SwiftData, and I can see that it is activating the transformer, but it keeps saying that I am still using NSArray instead of NSData. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "category"; desired type = NSData; given type = Swift.__SwiftDeferredNSArray; value = ( yo, gurt ).' terminating due to uncaught exception of type NSException CoreSimulator 1010.10 - Device: iPhone 16 18.0 (6879535B-3174-4025-AD37-ED06E60291AD) - Runtime: iOS 18.0 (22A3351) - DeviceType: iPhone 16 Message from debugger: killed @Model class MyModel: Identifiable, Equatable { @Attribute(.transformable(by: StringArrayTransformer.self)) var category: [String]? @Attribute(.transformable(by: StringArrayTransformer.self)) var amenities: [String]? var image: String? var parentChunck: HenricoPostDataChunk_V1? init(category: [String]?, amenities: [String]?) { self.category = category self.amenities = amenities } } class StringArrayTransformer: ValueTransformer { override func transformedValue(_ value: Any?) -> Any? { print(value) guard let array = value as? [String] else { return nil } let data = try? JSONSerialization.data(withJSONObject: array, options: []) print(data) return data } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } let string = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String] print(string) return string } override class func transformedValueClass() -> AnyClass { return NSData.self } override class func allowsReverseTransformation() -> Bool { return true } static func register() { print("regitsering") ValueTransformer.setValueTransformer(StringArrayTransformer(), forName: .stringArrayTransformerName) } } extension NSValueTransformerName { static let stringArrayTransformerName = NSValueTransformerName("StringArrayTransformer") }
3
0
186
Jul ’25
CoreData error=134100 Failed to open the store
Hello, I'm using CoreData + CloudKit and I am facing the following error 134100 "The managed object model version used to open the persistent store is incompatible with the one that was used to create the persistent store." All my schema updates are composed of adding optional attributes to existing entities, adding non-optional attributes (with default value) to existing entities or adding new entities Basically, only things that lightweight migrations can handle. Every time I update the schema, I add a new model version of xcdatamodel - who only has a single configuration (the "Default" one). And I also deploy the updated CloudKit schema from the dashboard. It worked up to v3 of my xcdatamodel, but started to crash for a few users at v4 when I added 16 new attributes (in total) to 4 existing entities. Then again at v5 when I added 2 new optional attributes to 1 existing entity. I'm using a singleton and here is the code: private func generateCloudKitContainer() -> NSPersistentCloudKitContainer { let container = NSPersistentCloudKitContainer(name: "MyAppModel") let fileLocation = URL(...) let description = NSPersistentStoreDescription(url: fileLocation) description.shouldMigrateStoreAutomatically = true description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) let options = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.com.company.MyApp") options.databaseScope = .private description.cloudKitContainerOptions = options container.persistentStoreDescriptions = [description] container.viewContext.automaticallyMergesChangesFromParent = true container.loadPersistentStores { description, error in container.viewContext.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType) if let error { // Error happens here! } } return container } I can't reproduce it yet. I don't really understand what could lead to this error.
4
0
908
Feb ’25
CloudKit Console: No Containers
Background: Our non-production App was using SwiftData locally. Yesterday we followed the documentation to enable CloudKit: https://developer.apple.com/documentation/cloudkit/enabling-cloudkit-in-your-app iCloud Works: Data is properly syncing via iCloud between 2 devices. Add on one shows on the other; delete on one deletes on the other. Today we logged into CloudKit Console for the first time; but there are no databases showing. We verified: Users and Roles: we have “Access to Cloud Managed… Certificates” Certificates, Identifiers & Profiles: our app has iCloud capabilities and is using our iCloud Container Signed into CloudKit Console with same developer ID as AppStoreConnect This is also the Apple ID of the iCloud account that has synced data from our app. In Xcode > Signing & Capabilities we are signed in as our Company team. Any guidance or tips to understanding how to what’s going on in CloudKit Console and gaining access to the database is appreciated!
1
0
156
Jun ’25
iCloud sync issues using NSPersistentCloudKitContainer for Core Data + CloudKit sync.
I have tried to set up iCloud sync. Despite fully isolating and resetting my development environment, the app fails with: NSCocoaErrorDomain Code=134060 (PersistentStoreIncompatibleVersionHashError) What I’ve done: Created a brand new CloudKit container Created a new bundle ID and app target Renamed the Core Data model file itself Set a new model version Used a new .sqlite store path Created a new .entitlements file with the correct container ID Verified that the CloudKit dashboard shows no records Deleted and reinstalled the app on a real device Also tested with “Automatically manage signing” and without Despite this, the error persists. I am very inexperienced and am not sure what my next step is to even attempt to fix this. Any guidance is apprecitated.
1
0
179
Jun ’25
Are these @model classes correct for swiftdata with cloudkit?
I have used core data before via the model editor. This is the first time I'm using swift data and that too with CloudKit. Can you tell me if the following model classes are correct? I have an expense which can have only one sub category which in turn belongs to a single category. Here are my classes... // Expense.swift // Pocket Expense Diary // // Created by Neerav Kothari on 16/05/25. // import Foundation import SwiftData @Model class Expense { @Attribute var expenseDate: Date? = nil @Attribute var expenseAmount: Double? = nil @Attribute var expenseCategory: Category? = nil @Attribute var expenseSubCategory: SubCategory? = nil var date: Date { get { return expenseDate ?? Date() } set { expenseDate = newValue } } var amount: Double{ get { return expenseAmount ?? 0.0 } set { expenseAmount = newValue } } var category: Category{ get { return expenseCategory ?? Category.init(name: "", icon: "") } set { expenseCategory = newValue } } var subCategory: SubCategory{ get { return expenseSubCategory ?? SubCategory.init(name: "", icon: "") } set { expenseSubCategory = newValue } } init(date: Date, amount: Double, category: Category, subCategory: SubCategory) { self.date = date self.amount = amount self.category = category self.subCategory = subCategory } } // // Category.swift // Pocket Expense Diary // // Created by Neerav Kothari on 16/05/25. // import Foundation import SwiftData @Model class Category { @Attribute var categoryName: String? = nil @Attribute var categoryIcon: String? = nil var name: String { get { return categoryName ?? "" } set { categoryName = newValue } } var icon: String { get { return categoryIcon ?? "" } set { categoryIcon = newValue } } @Relationship(inverse: \Expense.expenseCategory) var expenses: [Expense]? = [] init(name: String, icon: String) { self.name = name self.icon = icon } } // SubCategory.swift // Pocket Expense Diary // // Created by Neerav Kothari on 16/05/25. // import Foundation import SwiftData @Model class SubCategory { @Attribute var subCategoryName: String? = nil @Attribute var subCategoryIcon: String? = nil var name: String { get { return subCategoryName ?? "" } set { subCategoryName = newValue } } var icon: String { get { return subCategoryIcon ?? "" } set { subCategoryIcon = newValue } } @Relationship(inverse: \Expense.expenseSubCategory) var expenses: [Expense]? = [] init(name: String, icon: String) { self.name = name self.icon = icon } } The reason why I have wrappers is the let the existing code (before CloudKit was integrated), work. In future versions I plan to query expenses even via category or sub category. I particularly doubt for the relationship i have set. should there be one from category to subcategory as well?
1
0
109
Jun ’25
Documents folder of my app not shown in iCloud Drive in Finder
The problem is that the iCloud Drive directory of my app does not appear in my iCloud Drive in Finder despite the (I think) correct settings in my info.plist file (see below). In Terminal, I can see the folder and it also contains .txt files. What can I do to make the folder visible in Finder and the Files app? <key>NSUbiquitousContainers</key> <dict> <key>iCloud.vmk.NewsSwiper</key> <dict> <key>NSUbiquitousContainerIsDocumentScopePublic</key> <true/> <key>NSUbiquitousContainerName</key> <string>RSS-Filter</string> <key>NSUbiquitousContainerIdentifier</key> <string>iCloud.vmk.NewsSwiper</string> <key>NSUbiquitousContainerSupportedFolderLevels</key> <string>Any</string> </dict> </dict>
3
0
754
Feb ’25
What is going on with transformable
Hi, I keep trying to use transformable to store an array of strings with SwiftData, and I can see that it is activating the transformer, but it keeps saying that I am still using NSArray instead of NSData. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "category"; desired type = NSData; given type = Swift.__SwiftDeferredNSArray; value = ( yo, gurt ).' terminating due to uncaught exception of type NSException CoreSimulator 1010.10 - Device: iPhone 16 18.0 (6879535B-3174-4025-AD37-ED06E60291AD) - Runtime: iOS 18.0 (22A3351) - DeviceType: iPhone 16 Message from debugger: killed @Model class MyModel: Identifiable, Equatable { @Attribute(.transformable(by: StringArrayTransformer.self)) var category: [String]? @Attribute(.transformable(by: StringArrayTransformer.self)) var amenities: [String]? var image: String? var parentChunck: MyModelDataChunk_V1? init(category: [String]?, amenities: [String]?) { self.category = category self.amenities = amenities } } class StringArrayTransformer: ValueTransformer { override func transformedValue(_ value: Any?) -> Any? { print(value) guard let array = value as? [String] else { return nil } let data = try? JSONSerialization.data(withJSONObject: array, options: []) print(data) return data } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } let string = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String] print(string) return string } override class func transformedValueClass() -> AnyClass { return NSData.self } override class func allowsReverseTransformation() -> Bool { return true } static func register() { print("regitsering") ValueTransformer.setValueTransformer(StringArrayTransformer(), forName: .stringArrayTransformerName) } } extension NSValueTransformerName { static let stringArrayTransformerName = NSValueTransformerName("StringArrayTransformer") }
1
0
129
Jul ’25
Old CloudKit Data Repopulating after a Local Reset
We are trying to solve for the following condition with SwiftData + CloudKit: Lots of data in CloudKit Perform "app-reset" to clear data & App settings and start fresh. Reset data models with try modelContext.delete(model:_) myModel.count() confirms local deletion (0 records); but iCloud Console shows expectedly slow process to delete. Old CloudKit data is returning during the On Boarding process. Questions: • Would making a new iCloud Zone for each reset work around this, as the new zone would be empty? We're having trouble finding details about how to do this with SwiftData. • Would CKSyncEngine have a benefit over the default SwiftData methods? Open to hearing if anyone has experienced a similar challenge and how you worked around it!
2
0
196
Jun ’25
Mapping model not found if the attribute has "Preserve after deletion" enabled
I am trying to migrate my Core Data model to a new version with a new attribute added to it. Since my app supports macOS 13 I am not able to use the newly introduced Staged migrations. After much digging I found that the app is not able to find the Mapping Model when one of the attribute has "Preserve after deletion" enabled. I have enabled migration debbuging using com.apple.CoreData.MigrationDebug 1 I am getting following error error: CoreData: error: (migration) migration failed with error Error Domain=NSCocoaErrorDomain Code=134140 "Persistent store migration failed, missing mapping model." What is the way out here?
6
0
904
Feb ’25
Key-value storage will not sync data past a certain size
I have an app which uses key-value storage and will not sync data past a certain size -- meaning that device "A" will send the data to the cloud but device "B" will never receive the updated data. Device "B" will receive the NSUbiquitousKeyValueStoreDidChangeExternallyNotification that the KVS changed but the data is empty. The data in in the KVS is comprised of 4 keys, each containing a value of NSData generated by NSKeyedArchiver. The NSData is comprised of property-list data types (e.g. numbers, strings, dates, etc.) I've verified that the KVS meets the limits of: A total of 1 MB per app, with a per-key limit of 1 MB A per-key value size limit of 1 MB, and a maximum of 1024 keys A maximum length for key strings is 64 bytes using UTF8 encoding Also, the app has never received an NSUbiquitousKeyValueStoreQuotaViolationChange notification. Of the 4 keys, 3 of them contain no more than 30 KB of data each. However, one of the keys can contain as much as 160 KB of data which will not sync to another device. Strangely, if I constrain the data to 100 KB it will work, however, that is not ideal as it is a fraction of the necessary data. I don't see any errors in the debug log either. Any suggestions on what to try next to get this working?
2
0
156
May ’25
Migrating a swiftData project to CloudKit to implement iCloudSync.
My project is using swiftData and I want to implement iCloud sync in it. Now, my data base doesnt have any optional attributes or relationships and CloudKit wants them to be optional. So, rather than editing all code with unwrapping code for the optionals, how can I provide a bridge that does so in the last stage of actually saving to the store? Sort of, capture it in a proxy object before writing and after reading from the store. Is there a neat way that can save a lot of debugging? I have code snippets from chat gpt and they are hard to debug. This is my first project in swiftUI. Thanks. Neerav
3
0
150
Jun ’25
How to switch between Core Data Persistent Stores?
What is the best way to switch between Core Data Persistent Stores? My use case is that I have a multi-user app that stores thousands of data items unique to each user. To me, having Persistent Stores for each user seems like the best design to keep their data separate and private. (If anyone believes that storing the data for all users in one Persistent Store is a better design, I'd appreciate hearing from them.) Customers might switch users 5 to 10 times a day. Switching users must be fast, say a second or two at most.
1
0
91
Jun ’25
EXC_BAD_ACCESS When saving core data
I'm trying to convert some data, then save it back to Core Data. Sometimes this works fine without an issue, but occasionally I'll get an error Thread 1: EXC_BAD_ACCESS (code=1, address=0x0) It seems to occur when saving the core data context. I'm having trouble trying to debug it as it doesn't happen on the same object each time and can't reliably recreate the error Full view code can be found https://pastebin.com/d974V5Si but main functions below var body: some View { VStack { // Visual code here } .onAppear() { DispatchQueue.global(qos: .background).async { while (getHowManyProjectsToUpdate() > 0) { leftToUpdate = getHowManyProjectsToUpdate() updateLocal() } if getHowManyProjectsToUpdate() == 0 { while (getNumberOfFilesInDocumentsDirectory() > 0) { deleteImagesFromDocumentsDirectory() } if getNumberOfFilesInDocumentsDirectory() == 0 { DispatchQueue.main.asyncAfter(deadline: .now()) { withAnimation { self.isActive = true } } } } } } } update local function func updateLocal() { autoreleasepool { let fetchRequest: NSFetchRequest<Project> = Project.fetchRequest() fetchRequest.predicate = NSPredicate(format: "converted = %d", false) fetchRequest.fetchLimit = 1 fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Project.name, ascending: true), NSSortDescriptor(keyPath: \Project.name, ascending: true)] do { let projects = try viewContext.fetch(fetchRequest) for project in projects { currentPicNumber = 0 currentProjectName = project.name ?? "Error loading project" if let projectMain = project.mainPicture { currentProjectImage = getUIImage(picture: projectMain) } if let pictures = project.pictures { projectPicNumber = pictures.count // Get main image if let projectMain = project.mainPicture { if let imgThumbData = convertImageThumb(picture: projectMain) { project.mainPictureData = imgThumbData } } while (getTotalImagesToConvertForProject(project: project ) > 0) { convertImageBatch(project: project) } project.converted = true saveContext() viewContext.refreshAllObjects() } } } catch { print("Fetch Failed") } } } convertImageBatch function func convertImageBatch(project: Project) { autoreleasepool { let fetchRequestPic: NSFetchRequest<Picture> = Picture.fetchRequest() let projectPredicate = NSPredicate(format: "project = %@", project) let dataPredicate = NSPredicate(format: "pictureData == NULL") fetchRequestPic.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [projectPredicate, dataPredicate]) fetchRequestPic.fetchLimit = 5 fetchRequestPic.sortDescriptors = [NSSortDescriptor(keyPath: \Picture.dateTaken, ascending: true)] do { let pictures = try viewContext.fetch(fetchRequestPic) for picture in pictures { currentPicNumber = currentPicNumber + 1 if let imgData = convertImage(picture: picture), let imgThumbData = convertImageThumb(picture: picture) { // Save Converted picture.pictureData = imgData picture.pictureThumbnailData = imgThumbData // Save Image saveContext() viewContext.refreshAllObjects() } else { viewContext.delete(picture) saveContext() viewContext.refreshAllObjects() } } } catch { print("Fetch Failed") } } } And finally saving func saveContext() { do { try viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } }
6
0
202
Jul ’25
What is CloudKit error: AssetUploadTokenRetrieveRequest request size exceeds limit
Some of my customer get the following CloudKit error (I cannot reproduce is myself). Failed to modify some records (CKErrorDomain:2) userInfo: CKErrorDescription:Failed to modify some records CKPartialErrors:{ "<CKRecordID: ooo; recordName=ooo, zoneID=ooo:__defaultOwner__>" = "<CKError 0x600003809ce0: \"Limit Exceeded\" (27/2023); server message = \"AssetUploadTokenRetrieveRequest request size exceeds limit\"; op = ooo; uuid = ooo; container ID = \"ooo\">" This is a CKError.limitExeeded error. I create 200 or less records in a batch operation. So I am below the 400 limit. Searching the Internet for "AssetUploadTokenRetrieveRequest request size exceeds limit": 0 results Can anyone give me a hint?
5
0
761
Apr ’25
SwiftData One To Many
I'm working through the Develop In Swift tutorial at page [https://developer.apple.com/tutorials/develop-in-swift/navigation-editing-and-relationships-conclusion)] The tutorial has a one to many relationship between Friend and Movie (each friend can have at most one favorite movie and each movie can be the favorite for zero or more friends). An exercise left to the student is to use an .onDelete on the movie detail page to delete that movie as favorite. I modified the Form Form { TextField("Movie title", text: $movie.title) DatePicker("Release date", selection: $movie.releaseDate, displayedComponents: .date) if !movie.favoritedBy.isEmpty { Section("Favorited by") { ForEach(sortedFriends) { friend in Text(friend.name) } .onDelete(perform: deleteFavorites(indexes:)) } } } by adding the .onDelete clause I added private func deleteFavorites(indexes: IndexSet) { for index in indexes { context.delete(movie.favoritedBy[index]) } } to the view. This does delete the favorite movie, but it also deletes the friend. My assumption is that the selected friend should then have no favorite movie rather than being deleted There is an if in the Form that doesn't display the FAVORITED BY section if no friend has that movie as a favorite, but if I delete all the friends who had this movie as a favorite, the section remains (but is empty), until I exit the MovieDetail view and reload it There is no answer for these exercises, so I could be doing it wrong. EDIT: If I delete a movie using the app function to delete a movie, friends that have that movie as a favorite are not deleted and have their favorite movie set to None
3
0
768
Feb ’25
CoreData Data Sharing with AppGroup
I have the following lines of code to access data through CoreData. import Foundation import CoreData import CloudKit class CoreDataManager { static let instance = CoreDataManager() let container: NSPersistentCloudKitContainer let context: NSManagedObjectContext init() { container = NSPersistentCloudKitContainer(name: "ABC") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { print(error.userInfo) } }) context = container.viewContext context.automaticallyMergesChangesFromParent = true context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType) } func save() { do { try container.viewContext.save() print("Saved successfully") } catch { print("Error in saving data: \(error.localizedDescription)") } } } I have confirmed that I can share data between iPhone and iPad. Now, I need to use AppGroup as well. I have changed my code as follows. import Foundation import CoreData import CloudKit class CoreDataManager { static let shared = CoreDataManager() let container: NSPersistentContainer let context: NSManagedObjectContext init() { container = NSPersistentCloudKitContainer(name: "ABC") container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "some group name")!.appendingPathComponent("CoreDataMama.sqlite"))] container.loadPersistentStores(completionHandler: { (description, error) in if let error = error as NSError? { print("Unresolved error \(error), \(error.userInfo)") } }) context = container.viewContext context.automaticallyMergesChangesFromParent = true context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType) } func save() { do { try container.viewContext.save() print("Saved successfully") } catch { print("Error in saving data: \(error.localizedDescription)") } } } Other files being unaltered, my sample apps aren't sharing data. What am I doing wrong? Just FYI, I'm using actual devices. Thank you for your reading this topic.
1
0
108
May ’25
removing the beta developer tab from your phone settings
Hello, on every Apple device, iPhone/Watch I have the option to install developer beta versions. I would like to unsubscribe from developer beta versions - not have them in settings. I know that developer beta is assigned to my iCloud account. After logging out and restoring factory settings, the tab disappears. When I log into my iCloud account, it appears everywhere. I did not sign up for developer beta. How do I remove it?
4
0
985
Jan ’25