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

Sync an interactive widget's Core Data store with the main app (and iCloud)
Hi everyone! I have an app on the App Store that uses Core Data as its data store. (It's called Count on Me: Tally Counter. Feel free to check it out.) One of the app's core feature is an interactive widget with a simple button. When the button is tapped, it's supposed to update the entity in the store. My requirement is that the changes are then reflected with minimal latency in the main app and – ideally – also on other devices of the same iCloud user. And vice-versa: When an entity is updated in the app (or on another device where the same iCloud user is logged in), the widget that shows this entity should also refresh to reflect the changes. I have read multiple articles, downloaded sample projects, searched Stackoverflow and the Apple developer forums, and tried to squeeze a solution out of AI, but couldn't figure out how to make this work reliably. So I tried to reduce the core problem to a minimal example project. It has two issues that I cannot resolve: When I update an entity in the app, the widget is immediately updated as intended (due to a call to WidgetCenter's reloadAllTimelines method). However, when I update the same entity from the interactive widget using the same app intent, the changes are not reflected in the main app. For the widget and the app to use the same local data store, I need to enable App Groups in both targets and set a custom location for the store within the shared app group. So I specify a custom URL for the NSPersistentStoreDescription when setting up the Core Data stack. The moment I do this, iCloud sync breaks. Issue no. 1 is far more important to me as I haven't officially enabled iCloud sync yet in my real app that's already on the App Store. But it would be wonderful to resolve issue no. 2 as well. Surely, there must be a way to synchronize changes to the source of truth triggered by interactive widget with other devices of the same iCloud user. Otherwise, the feature to talk to the main app and the feature to synchronize with iCloud would be mutually exclusive. Some other developers I talked to have suggested that the widget should only communicate proposed changes to the main app and once the main app is opened, it processes these changes and writes them to the NSPersistentCloudKitContainer which then synchronizes across devices. This is not an option for me as it would result in a stale state and potential data conflicts with different devices. For example, when a user has the same widget on their iPhone and their iPad, taps a button on the iPhone widget, that change would not be reflected on the iPad widget until the user decides to open the app on the iPhone. At the same time, the user could tap the button multiple times on their iPad widget, resulting in a conflicting state on both devices. Thus, this approach is not a viable solution. An answer to this question will be greatly appreciated. The whole code including the setup of the Core Data stack is included in the repository reference above. Thank you!
4
1
408
Apr ’25
Mac Assigning NSManagedObject to NSPersistentStore
Hello, I have a iOS app I was looking at porting to Mac. I'm having an issue with both the Mac (Designed for iPad) and Mac Catalyst Destinations. I can't test Mac due to too many build issues. I'm trying to assign a new NSManagedObject into a NSPersistentStore. let object = MyObject(context: context) context.assign(object, to: nsPersistentStore) This works fine for iOS/iOS Simulator/iPhone/iPad. But on the Mac it's crashing with FAULT: NSInvalidArgumentException: Can't assign an object to a store that does not contain the object's entity.; { Thread 1: "Can't assign an object to a store that does not contain the object's entity."
4
0
134
6d
Asset Pack Limit
I have a total of 100 asset packs associated with my app but I have archived 5 of them. Unfortunately I am now unable to upload any more asset packs (the reported error is "backgroundAsset limit reached -- This app has already reached the maximum number of active backgroundAssets. Maximum allowed is 100.") I assumed that archiving asset packs would make them inactive (and thus not count against the limit). This seems to not be the case and I'm not sure how I can upload new asset packs.
4
0
262
Jan ’26
CloudKit references — is this a forward reference or a back reference?
I'm trying to understand the terminology around forward vs backward references in CloudKit. Say I have two record types: User LeaderboardScore (a score belongs to a user) The score record stores a user reference: score["user"] = CKRecord.Reference( recordID: userRecordID, action: .deleteSelf ) So: LeaderboardScore → User The user record does not store any references to scores From a data-model perspective: Is this considered a forward reference (child → parent)? Or a back reference, since the score is "pointing back" to its owner? My use case is having leaderboard in my app and so i have created a user table to store all the users and a score table for saving the scores of each user of the app.
4
0
104
2d
Xcode 26.1 / OS 26.1 regression with schema and macros
After Xcode 26.1 was updated and installing the OS 26.1 simulators, my app started crashing related to transformable properties. When I checked my schema, I noticed that properties with array collection types are suddenly set with an option transformable with Optional("NSSecureUnarchiveFromData")], even though I do not use any transformable types. I verified the macros, no transformable was specified. This is causing ModelCoders to encode/decode my properties incorrectly. This is not an issue when I switch back to OS 26.0 simulators.
4
0
414
Nov ’25
iOS 26 SwiftData crash does not happen in iOS 16
I have a simple app that makes an HTTPS call to gather some JSON which I then parse and add to my SwiftData database. The app then uses a simple @Query in a view to get the data into a list. on iOS 16 this works fine. No problems. But the same code on iOS 26 (targeting iOS 18.5) crashes after about 15 seconds of idle time after the list is populated. The error message is: Could not cast value of type '__NSCFNumber' (0x1f31ee568) to 'NSString' (0x1f31ec718). and occurs when trying to access ANY property of the list. I have a stripped down version of the app that shows the crash available. To replicate the issue: open the project in Xcode 26 target any iOS 26 device or simulator compile and run the project. after the list is displayed, wait about 15 seconds and the app crashes. It is also of note that if you try to run the app again, it will crash immediately, unless you delete the app from the device. Any help on this would be appreciated. Feedback number FB20295815 includes .zip file Below is the basic code (without the data models) The Best Seller List.Swift import SwiftUI import SwiftData @main struct Best_Seller_ListApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer (for: NYTOverviewResponse.self) } } ContentView.Swift import os.log import SwiftUI struct ContentView: View { @Environment(\.modelContext) var modelContext @State private var listEncodedName = String() var body: some View { NavigationStack () { ListsView() } .task { await getBestSellerLists() } } func getBestSellerLists() async { guard let url = URL(string: "https://api.nytimes.com/svc/books/v3/lists/overview.json?api-key=\(NYT_API_KEY)") else { Logger.errorLog.error("Invalid URL") return } do { let decoder = JSONDecoder() var decodedResponse = NYTOverviewResponse() //decode the JSON let (data, _) = try await URLSession.shared.data(from: url) decoder.keyDecodingStrategy = .convertFromSnakeCase decodedResponse = try decoder.decode(NYTOverviewResponse.self, from: data) //remove any lists that don't have list_name_encoded. Fixes a bug in the data decodedResponse.results!.lists = decodedResponse.results!.lists!.filter { $0.listNameEncoded != "" } // sort the lists decodedResponse.results!.lists!.sort { (lhs, rhs) -> Bool in lhs.displayName < rhs.displayName } //delete any potential existing data try modelContext.delete(model: NYTOverviewResponse.self) //add the new data modelContext.insert(decodedResponse) } catch { Logger.errorLog.error("\(error.localizedDescription)") } } } ListsView.Swift import os.log import SwiftData import SwiftUI @MainActor struct ListsView: View { //MARK: - Variables and Constants @Query var nytOverviewResponses: [NYTOverviewResponse] enum Updated: String { case weekly = "WEEKLY" case monthly = "MONTHLY" } //MARK: - Main View var body: some View { List { if nytOverviewResponses.isEmpty { ContentUnavailableView("No lists yet", systemImage: "list.bullet", description: Text("NYT Bestseller lists not downloaded yet")) } else { WeeklySection MonthlySection } } .navigationBarTitle("Bestseller Lists", displayMode: .large) .listStyle(.grouped) } var WeeklySection: some View { let rawLists = nytOverviewResponses.last?.results?.lists ?? [] // Build a value-typed array to avoid SwiftData faulting during sort let weekly = rawLists .filter { $0.updateFrequency == Updated.weekly.rawValue } .map { (name: $0.displayName, encoded: $0.listNameEncoded, model: $0) } .sorted { $0.name < $1.name } return Section(header: Text("Weekly lists to be published on \(nytOverviewResponses.last?.results?.publishedDate ?? "-")")) { ForEach(weekly, id: \.encoded) { item in Text(item.name).font(Font.custom("Georgia", size: 17)) } } } var MonthlySection: some View { let rawLists = nytOverviewResponses.last?.results?.lists ?? [] // Build a value-typed array to avoid SwiftData faulting during sort let monthly = rawLists .filter { $0.updateFrequency == Updated.monthly.rawValue } .map { (name: $0.displayName, encoded: $0.listNameEncoded, model: $0) } .sorted { $0.name < $1.name } return Section(header: Text("Monthly lists to be published on \(nytOverviewResponses.last?.results?.publishedDate ?? "-")")) { ForEach(monthly, id: \.encoded) { item in Text(item.name).font(Font.custom("Georgia", size: 17)) } } } }
4
0
245
Sep ’25
macOS to macOS SwiftData iCloud Sync Problems
I am a novice developer, so please be kind. 😬 I am developing a simple macOS app backed with SwiftData and trying to set up iCloud sync so data syncs between two Macs running the app. I have added the iCloud capability, checked the CloudKit box, and selected an iCloud Container. Per suggestion of Paul Hudson, my model properties have either default values or are marked as optional, and the only relationship in my model is marked as optional. @Model final class Project { // Stable identifier used for restoring selected project across launches. var uuid: UUID? var name: String = "" var active: Bool = true var created: Date = Foundation.Date(timeIntervalSince1970: 0) var modified: Date = Foundation.Date(timeIntervalSince1970: 0) // CloudKit requires to-many relationships to be optional in this schema. @Relationship var timeEntries: [TimeEntry]? init(name: String, active: Bool = true, uuid: UUID? = UUID()) { self.uuid = uuid self.name = name self.active = active self.created = .now self.modified = .now self.timeEntries = [] } @Model final class TimeEntry { // Core timing fields. var start: Date = Foundation.Date(timeIntervalSince1970: 0) var end: Date = Foundation.Date(timeIntervalSince1970: 0) var codeRawValue: String? var activitiesRawValue: String = "" // Inverse relationship back to the owning project. @Relationship(inverse: \Project.timeEntries) var project: Project? init( start: Date = .now, end: Date = .now.addingTimeInterval(60 * 60), code: BillingCode? = nil, activities: [ActivityType] = [] ) { self.start = start self.end = end self.codeRawValue = code?.rawValue self.activitiesRawValue = Self.serializeActivities(activities) } I have set up the following in the AppDelegate for registering for remote notifications as well as some logging to console that the remote notification token was received and to be notified when when I am receiving remote notifications. private final class TimeTrackerAppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { print("📡 [Push] Registering for remote notifications") NSApplication.shared.registerForRemoteNotifications() } func application(_ application: NSApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let tokenPreview = deviceToken.map { String(format: "%02x", $0) }.joined().prefix(16) print("✅ [Push] Registered for remote notifications (token prefix: \(tokenPreview)...)") } func application(_ application: NSApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { let nsError = error as NSError print("❌ [Push] Failed to register for remote notifications: \(nsError.domain) (\(nsError.code)) \(nsError.localizedDescription)") } func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String: Any]) { print("📬 [Push] Received remote notification: \(userInfo)") } } In testing, I run the same commit from Xcode on two different Macs logged into the same iCloud account. My problem is that sync is not reliably working. Starting up the app on both Macs shows that the app successfully registered for remote notifications. Sometimes, making an edit on Mac 1 is immediately reflected in Mac 2 UI along with didReceiveRemoteNotification message (all occurring while the Mac 2 app remains in foreground). Sometimes, the Mac 2 app needs to be backgrounded and re-foregrounded before the UI shows the updated data. Sometimes, an edit on Mac 2 will show on Mac 1 only after re-foregrounded but not show any didReceiveRemoteNotification on the Mac 1 console. Sometimes, an edit on Mac 2 will not show at all on Mac 1 even after re-foregrounding the app. Sometimes, no edits sync between either Mac. I had read about how a few years back, there was a bug in macOS where testing iCloud sync between Macs did not work while running from Xcode but would work in TestFlight. For me, running my app in TestFlight on both Macs has never been able to sync any edits between the Macs. Any idea where I might be going wrong. It seems this should not be this hard and should not be failing so inconsistently. Wondering what I might be doing wrong here.
4
0
133
2w
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
203
Jul ’25
CloudKit keyvalue pair debug ?
Hello ! I am using this iCloud key value pair mechanism to save small app configuration between iOS and tvOS. I would say it is working. But when I go back and forth between debug and release (TestFlight) modes, it is like both apps are not connected anymore. I spend a lot of time restarting all devices, rebuilding, activating / deactivating iCloud capabilities in the Xcode project. It is like the app is mixing debug and release data. Is there an easy way to check what is happening exactly ? I know there's nothing on CloudKit console, so .... Thank you Frederic
3
0
375
Mar ’25
CloudKit container name
I have a new app I am working on, it uses, a container id like com.me.mycompany.FancyApp.prod, the description in the app is My Fancy App. When I deploy the app via TestFlight on a real device, the sync seems to work, but when I view iCloud->Storage-List, I see my app icon, and the name "prod". Where did the name prod come from? It should be My Fancy App, which is the actual name of the App.
3
0
163
Jan ’26
Strange behavior with 100k+ records in NSPersistentCloudKitContainer
I have been using the basic NSPersistentContainer with 100k+ records for a while now with no issues. The database size can fluctuate a bit but on average it takes up about 22mb on device. When I switch the container to NSPersistentCloudKitContainer, I see a massive increase in size to ~150mb initially. As the sync engine uploads records to iCloud it has ballooned to over 600mb on device. On top of that, the user's iCloud usage in settings reports that it takes up 1.7gb in the cloud. I understand new tables are added and history tracking is enabled but the size increase seems a bit drastic. I'm not sure how we got from 22mb to 1.7gb with the exact same data. A few other things that are important to note: I import all the 100k+ records at once when testing the different containers. At the time of the initial import there is only 1 relation (an import group record) that all the records are attached to. I save the background context only once after all the records and the import group have been made and added to the context. After the initial import, some of these records may have a few new relations added to them over time. I suppose this could be causing some of the size increase, but its only about 20,000 records that are updated. None of the records include files/ large binary data. Most of the attributes are encrypted. I'm syncing to the dev iCloud environment. When I do make a change to a single attribute in a record, CloudKit reports that every attribute has been modified (not sure if this is normal or not ) Also, When syncing to a new device, the sync can take hours - days. I'm guessing it's having to sync both the new records and the changes, but it exponentially gets slower as more records are downloaded. The console will show syncing activity, but new records are being added at a slower rate as more records are added. After about 50k records, it grinds to a halt and while the console still shows sync activity, only about 100 records are added every hour. All this to say i'm very confused where these issues are coming from. I'm sure its a combination of how i've setup my code and the vast record count, record history, etc. If anyone has any ideas it would be much appreciated.
3
1
833
Nov ’25
CoreData not documented UserInfo Notification
Hello, the last days I was trying to solve a bug in my Unit Tests related to the CoreData "NSManagedObjectContextObjectsDidChange" Notification. Im using some kind of Notification handler to save and abstract that for the UI and while the tests are running this notification was triggered with objects that doesn't exists anymore, which has resulted in a crash. After some debugging I have detected, that the objects in here are really old. The objects here was from few tests ago, where a Merge Conflict happened. In the meantime there was a plenty of resets and deletes of the whole db. I have also seen that the bad notification is the first in the stack trace of the main thread, which is in my opinion also not usual. So the real question is: The only difference what I have found for the bad notification to the real notification, was the existence of the key "NSObjectsChangedByMergeChangesKey" in the UserInfo dictionary of the ObjectsDidChange Notification. But this key is nowhere found in the documentation of Apple. Also the search engines does not produce any result. So what is this key and when is this key contained in this notification and when not? Maybe if I understand this, it helps me to understand the overall issue ...
3
0
258
Nov ’25
Can't get CloudKit to load data on cloud
The app works on a local db but when I try to make it work with iCloud I get errors that I don't understand. CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1247): <NSCloudKitMirroringDelegate: 0x10664c200>: Failed to set up CloudKit integration for store: <NSSQLCore: 0x106688140> (URL: file:///var/mobile/Containers/Data/Application/20EF350F-F0FA-4132-97DA-61B60AADB101/Library/Application%20Support/default.store) <CKError 0x109430e40: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 82ED152A-D015-414D-BB79-AF36E5AF4A8B; container ID = "iCloud.se.Grindegard.MinaRecept"; partial errors: { com.apple.coredata.cloudkit.zone:defaultOwner = <CKError 0x109431230: "Permission Failure" (10/2007); server message = "Invalid bundle ID for container"; op = E56A3CDA393641F8; uuid = 82ED152A-D015-414D-BB79-AF36E5AF4A8B> }> what can be wrong?
3
0
61
Jul ’25
SwiftUI & SwiftData: Fatal Error "Duplicate keys of type" Occurs on First Launch
I'm developing a SwiftUI app using SwiftData and encountering a persistent issue: Error Message: Thread 1: Fatal error: Duplicate keys of type 'Bland' were found in a Dictionary. This usually means either that the type violates Hashable's requirements, or that members of such a dictionary were mutated after insertion. Details: Occurrence: The error always occurs on the first launch of the app after installation. Specifically, it happens approximately 1 minute after the app starts. Inconsistent Behavior: Despite no changes to the code or server data, the error occurs inconsistently. Data Fetching Process: I fetch data for entities (Bland, CrossZansu, and Trade) from the server using the following process: Fetch Bland and CrossZansu entities via URLSession. Insert or update these entities into the SwiftData context. The fetched data is managed as follows: func refleshBlandsData() async throws { if let blandsOnServer = try await DataModel.shared.getBlands() { await MainActor.run { blandsOnServer.forEach { blandOnServer in if let blandOnLocal = blandList.first(where: { $0.code == blandOnServer.code }) { blandOnLocal.update(serverBland: blandOnServer) } else { modelContext.insert(blandOnServer.bland) } } } } } This is a simplified version of my StockListView. The blandList is a @Query property and dynamically retrieves data from SwiftData: struct StockListView: View { @Environment(\.modelContext) private var modelContext @Query(sort: \Bland.sname) var blandList: [Bland] @Query var users: [User] @State private var isNotLoaded = true @State private var isLoading = false @State private var loadingErrorState = "" var body: some View { NavigationStack { List { ForEach(blandList, id: \.self) { bland in NavigationLink(value: bland) { Text(bland.sname) } } } .navigationTitle("Stock List") .onAppear { doIfFirst() } } } // This function handles data loading when the app launches for the first time func doIfFirst() { if isNotLoaded { loadDataWithAnimationIfNotLoading() isNotLoaded = false } } // This function ensures data is loaded with an animation and avoids multiple triggers func loadDataWithAnimationIfNotLoading() { if !isLoading { isLoading = true Task { do { try await loadData() } catch { // Capture and store any errors during data loading loadingErrorState = "Data load failed: \(error.localizedDescription)" } isLoading = false } } } // Fetch data from the server and insert it into the SwiftData model context func loadData() async throws { if let blandsOnServer = try await DataModel.shared.getBlands() { for bland in blandsOnServer { // Avoid inserting duplicate keys by checking for existing items in blandList if !blandList.contains(where: { $0.code == bland.code }) { modelContext.insert(bland.bland) } } } } } Entity Definitions: Here are the main entities involved: Bland: @Model class Bland: Identifiable { @Attribute(.unique) var code: String var sname: String @Relationship(deleteRule: .cascade, inverse: \CrossZansu.bland) var zansuList: [CrossZansu] @Relationship(deleteRule: .cascade, inverse: \Trade.bland) var trades: [Trade] } CrossZansu: @Model class CrossZansu: Equatable { @Attribute(.unique) var id: String var bland: Bland? } Trade: @Model class Trade { @Relationship(deleteRule: .nullify) var user: User? var bland: Bland } User: class User { var id: UUID @Relationship(deleteRule: .cascade, inverse: \Trade.user) var trades: [Trade] } Observations: Error Context: The error occurs after the data is fetched and inserted into SwiftData. This suggests an issue with Hashable requirements or duplicate keys being inserted unintentionally. Concurrency Concerns: The fetch and update operations are performed in asynchronous tasks. Could this cause race conditions? Questions: Could this issue be related to how @Relationship and @Attribute(.unique) are managed in SwiftData? What are potential pitfalls with Equatable implementations (e.g., in CrossZansu) when used in SwiftData entities? Are there any recommended approaches for debugging "Duplicate keys" errors in SwiftData? Additional Info: Error Timing: The error occurs only during the app's first launch and consistently within the first minute.
3
1
631
Apr ’25
NSPersistentCloudKitContainer data loss edge case
Hi, I was testing the new iOS 18 behavior where NSPersistentCloudKitContainer wipes the local Core Data store if the user logs out of iCloud, for privacy purposes. I ran the tests both with a Core Data + CloudKit app, and a simple one using SwiftData with CloudKit enabled. Results were identical in either case. In my testing, most of the time, the feature worked as expected. When I disabled iCloud for my app, the data was wiped (consistent with say the Notes app, except if you disable iCloud it warns you that it'll remove those notes). When I re-enabled iCloud, the data appeared. (all done through the Settings app) However, in scenarios when NSPersistentCloudKitContainer cannot immediately sync -- say due to rate throttling -- and one disables iCloud in Settings, this wipes the local data store and ultimately results in data loss. This occurs even if the changes to the managed objects are saved (to the local store) -- it's simply they aren't synced in time. It can be a little hard to reproduce the issue, especially since when you exit to the home screen from the app, it generally triggers a sync. To avoid this, I swiped up to the screen where you can choose which apps to close, and immediately closed mine. Then, you can disable iCloud, and run the app again (with a debugger is helpful). I once saw a message with something along the lines of export failed (for my record that wasn't synced), and unfortunately it was deleted (and never synced). Perhaps before NSPersistentCloudKitContainer wipes the local store it ought to force sync with the cloud first?
3
0
358
Jan ’26
Avoid Duplicate Records with CloudKit & CoreData
When my app starts it loads data (of vehicle models, manufacturers, ...) from JSON files into CoreData.  This content is static. Some CoreData entities have fields that can be set by the user, for example an isFavorite boolean field. How do I tell CloudKit that my CoreData objects are 'static' and must not be duplicated on other devices (that will also load it from JSON files). In other words, how can I make sure that the CloudKit knows that the record created from JSON for vehicle model XYZ on one device is the same record that was created from JSON on any other device? I'm using NSPersistentCloudKitContainer.
3
2
3.4k
Jun ’25
NSFileVersion.currentVersionOfItem not consistent across devices after simultaneous edit
I’m building an app that edits files in iCloud and uses an NSFilePresenter to monitor changes. When a conflict occurs, the system calls presentedItemDidGain(_:). In that method, I merge the versions by reading the current (canonical) version using NSFileVersion.currentVersionOfItem(at:) and the conflicting ones using NSFileVersion.unresolvedConflictVersionsOfItem(at:). This generally works, but sometimes, if two devices edit the same file at the same time, each device sees its own local version as the current one. For example: Device A writes fileVerA (slightly later in real time) Device B writes fileVerB On Device A all works fine, currentVersionOfItem returns fileVerA, as expected, and unresolvedConflictVersionsOfItem returns [fileVerB]. But on Device B, currentVersionOfItem returns fileVerB!? And unresolvedConflictVersionsOfItem returns the same, local file [fileVerB], without any hint of the other conflicting version, fileVerA. Later, the newer version from the Device A arrives on Device B as a normal, non-conflicting update via presentedItemDidChange(_:). This seems to contradict Apple’s documentation: “The currentVersionOfItemAtURL: method returns an NSFileVersion object representing what’s referred to as the current file; the current file is chosen by iCloud on some basis as the current “conflict winner” and is the same across all devices.” Is this expected behavior, or a bug in how iCloud reports file versions?
3
0
240
Oct ’25
SwiftData: Unexpected backing data for snapshot creation
When deleting a SwiftData entity, I sometimes encounter the following error in a document based SwiftUI app: Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<MyEntityClass> The deletion happens in a SwiftUI View and the code used to retrieve the entity is standard (the ModelContext is injected from the @Environment): let myEntity = modelContext.model(for: entityIdToDelete) modelContext.delete(myEntity) Unfortunately, I haven't yet managed to isolate this any further in order to come up with a reproducible PoC. Could you give me further information about what this error means?
3
0
249
Oct ’25