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

SwiftData migration crashes when working with relationships
The following complex migration consistently crashes the app with the following error: SwiftData/PersistentModel.swift:726: Fatal error: What kind of backing data is this? SwiftData._KKMDBackingData<SwiftDataMigration.ItemSchemaV1.ItemList> My app relies on a complex migration that involves these optional 1 to n relationships. Theoretically I could not assign the relationships in the willMigrate block but afterwards I am not able to tell which list and items belonged together. Steps to reproduce: Run project Change typealias CurrentSchema to ItemSchemaV2 instead of ItemSchemaV1. Run project again -> App crashes My setup: Xcode Version 16.2 (16C5032a) MacOS Sequoia 15.4 iPhone 12 with 18.3.2 (22D82) Am I doing something wrong or did I stumble upon a bug? I have a demo Xcode project ready but I could not upload it here so I put the code below. Thanks for your help typealias CurrentSchema = ItemSchemaV1 typealias ItemList = CurrentSchema.ItemList typealias Item = CurrentSchema.Item @main struct SwiftDataMigrationApp: App { var sharedModelContainer: ModelContainer = { do { return try ModelContainer(for: ItemList.self, migrationPlan: MigrationPlan.self) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } This is the migration plan enum MigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [ItemSchemaV1.self, ItemSchemaV2.self] } static var stages: [MigrationStage] = [ MigrationStage.custom(fromVersion: ItemSchemaV1.self, toVersion: ItemSchemaV2.self, willMigrate: { context in print("Started migration") let oldlistItems = try context.fetch(FetchDescriptor<ItemSchemaV1.ItemList>()) for list in oldlistItems { let items = list.items.map { ItemSchemaV2.Item(timestamp: $0.timestamp)} let newList = ItemSchemaV2.ItemList(items: items, name: list.name, note: "This is a new property") context.insert(newList) context.delete(list) } try context.save() // Crash indicated here print("Finished willMigrate") }, didMigrate: { context in print("Did migrate successfully") }) ] } The versioned schemas enum ItemSchemaV1: VersionedSchema { static var versionIdentifier = Schema.Version(1, 0, 0) static var models: [any PersistentModel.Type] { [Item.self] } @Model final class Item { var timestamp: Date var list: ItemSchemaV1.ItemList? init(timestamp: Date) { self.timestamp = timestamp } } @Model final class ItemList { @Relationship(deleteRule: .cascade, inverse: \ItemSchemaV1.Item.list) var items: [Item] var name: String init(items: [Item], name: String) { self.items = items self.name = name } } } enum ItemSchemaV2: VersionedSchema { static var versionIdentifier = Schema.Version(2, 0, 0) static var models: [any PersistentModel.Type] { [Item.self] } @Model final class Item { var timestamp: Date var list: ItemSchemaV2.ItemList? init(timestamp: Date) { self.timestamp = timestamp } } @Model final class ItemList { @Relationship(deleteRule: .cascade, inverse: \ItemSchemaV2.Item.list) var items: [Item] var name: String var note: String init(items: [Item], name: String, note: String = "") { self.items = items self.name = name self.note = note } } } Last the ContentView: struct ContentView: View { @Query private var itemLists: [ItemList] var body: some View { NavigationSplitView { List { ForEach(itemLists) { list in NavigationLink { List(list.items) { item in Text(item.timestamp.formatted(date: .abbreviated, time: .complete)) } .navigationTitle(list.name) } label: { Text(list.name) } } } .navigationTitle("Crashing migration demo") .onAppear { if itemLists.isEmpty { for index in 0..<10 { let items = [Item(timestamp: Date.now)] let listItem = ItemList(items: items, name: "List No. \(index)") modelContext.insert(listItem) } try! modelContext.save() } } } detail: { Text("Select an item") } } }
1
1
182
Apr ’25
Login issues on CloudKit Console
Hi everyone In the last 24 hours, I’ve been running into some issues with the CloudKit console. Most of the time, I‘ll get an error stating an error has caused this web page to stop working correctly. Reloading doesn’t fix the issue, nor does using different browsers: Today I’ve got another error, something along the lines of the Console not being able to fetch the teams I’m assigned to and an XHF error pop-up. Has anyone encountered the same issues? After trying multiple times, I’m able to reach my database but it’s a bit frustrating as it’s very unreliable this way. Thanks for your feedback! Dave
1
3
135
May ’25
Best practice for centralizing SwiftData query logic and actions in an @Observable manager?
I'm building a SwiftUI app with SwiftData and want to centralize both query logic and related actions in a manager class. For example, let's say I have a reading app where I need to track the currently reading book across multiple views. What I want to achieve: @Observable class ReadingManager { let modelContext: ModelContext // Ideally, I'd love to do this: @Query(filter: #Predicate<Book> { $0.isCurrentlyReading }) var currentBooks: [Book] // ❌ But @Query doesn't work here var currentBook: Book? { currentBooks.first } func startReading(_ book: Book) { // Stop current book if any if let current = currentBook { current.isCurrentlyReading = false } book.isCurrentlyReading = true try? modelContext.save() } func stopReading() { currentBook?.isCurrentlyReading = false try? modelContext.save() } } // Then use it cleanly in any view: struct BookRow: View { @Environment(ReadingManager.self) var manager let book: Book var body: some View { Text(book.title) Button("Start Reading") { manager.startReading(book) } if manager.currentBook == book { Text("Currently Reading") } } } The problem is @Query only works in SwiftUI views. Without the manager, I'd need to duplicate the same query in every view just to call these common actions. Is there a recommended pattern for this? Or should I just accept query duplication across views as the intended SwiftUI/SwiftData approach?
1
0
402
Jan ’26
Core Data crash while trying to merge
I'm looking for guidance how to mitigate this crash. It seems super deep inside Core Data' FRC fetchedObjects management. In my code, it's initiated by this viewContext.perform { [unowned self] in self.viewContext.mergeChanges(fromContextDidSave: notification) } which is directly followed by the stack trace below. Basically merging data from .NSManagedObjectContextDidSave notification from another NSManagedObjectContext. Nothing special, it works great for years, apart from these rare occurrences. Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Reason: -[__NSCFArray objectAtIndex:]: index (235) beyond bounds (234) Termination Reason: SIGNAL 6 Abort trap: 6 Triggered by Thread: 0 Last Exception Backtrace: 0 CoreFoundation 0x199e947cc __exceptionPreprocess + 164 (NSException.m:249) 1 libobjc.A.dylib 0x1971672e4 objc_exception_throw + 88 (objc-exception.mm:356) 2 CoreFoundation 0x199fc4258 _NSArrayRaiseBoundException + 368 (NSCFArray.m:22) 3 CoreFoundation 0x199e288a4 -[__NSCFArray objectAtIndex:] + 200 (NSCFArray.m:42) 4 CoreData 0x1a1e17338 -[_PFMutableProxyArray objectAtIndex:] + 40 (_PFArray.m:1860) 5 CoreData 0x1a1e1673c -[NSFetchedResultsController _updateFetchedObjectsWithInsertChange:] + 380 (NSFetchedResultsController.m:1582) 6 CoreData 0x1a1e1426c __82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 2240 (NSFetchedResultsController.m:2171) 7 CoreData 0x1a1dcdf80 developerSubmittedBlockToNSManagedObjectContextPerform + 156 (NSManagedObjectContext.m:4002) 8 CoreData 0x1a1e41a44 -[NSManagedObjectContext performBlockAndWait:] + 216 (NSManagedObjectContext.m:4113) 9 CoreData 0x1a1e41034 -[NSFetchedResultsController _core_managedObjectContextDidChange:] + 124 (NSFetchedResultsController.m:2379) 10 CoreFoundation 0x199e632f4 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 148 (CFNotificationCenter.c:701) 11 CoreFoundation 0x199e63210 ___CFXRegistrationPost_block_invoke + 88 (CFNotificationCenter.c:194) 12 CoreFoundation 0x199e63158 _CFXRegistrationPost + 436 (CFNotificationCenter.c:222) 13 CoreFoundation 0x199e6170c _CFXNotificationPost + 728 (CFNotificationCenter.c:1248) 14 Foundation 0x198a84ea4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 92 (NSNotification.m:531) 15 CoreData 0x1a1e11650 -[NSManagedObjectContext _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1736 (NSManagedObjectContext.m:8098) 16 CoreData 0x1a1e10e0c -[NSManagedObjectContext _postRefreshedObjectsNotificationAndClearList] + 164 (NSManagedObjectContext.m:7631) 17 CoreData 0x1a1e0fad8 -[NSManagedObjectContext _processRecentChanges:] + 100 (NSManagedObjectContext.m:7714) 18 CoreData 0x1a1e3563c -[NSManagedObjectContext _coreMergeChangesFromDidSaveDictionary:usingObjectIDs:withClientQueryGeneration:] + 3436 (NSManagedObjectContext.m:3723) 19 CoreData 0x1a1e34350 __116+[NSManagedObjectContext(_NSCoreDataSPI) _mergeChangesFromRemoteContextSave:intoContexts:withClientQueryGeneration:]_block_invoke_4 + 76 (NSManagedObjectContext.m:9531) 20 CoreData 0x1a1dcdf80 developerSubmittedBlockToNSManagedObjectContextPerform + 156 (NSManagedObjectContext.m:4002) 21 CoreData 0x1a1e41a44 -[NSManagedObjectContext performBlockAndWait:] + 216 (NSManagedObjectContext.m:4113) 22 CoreData 0x1a1e39880 +[NSManagedObjectContext _mergeChangesFromRemoteContextSave:intoContexts:withClientQueryGeneration:] + 2372 (NSManagedObjectContext.m:9537) 23 CoreData 0x1a1e344a0 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 292 (NSManagedObjectContext.m:0)
1
0
75
Apr ’25
CKSyncEngine on macOS: Automatic Fetch Extremely Slow Compared to iOS
Hi everyone, We’re currently using CKSyncEngine to sync all our locally persisted data across user devices (iOS and macOS) via iCloud. We’ve noticed something strange and reproducible: On iOS, when the CKSyncEngine is initialized with manual sync behavior, both manual calls to fetchChanges() and sendChanges() happen nearly instantly (usually within seconds). Automatic syncing is also very fast. On macOS, when the CKSyncEngine is initialized with manual sync behavior, fetchChanges() and sendChanges() are also fast and responsive. However, once CKSyncEngine is initialized with automatic syncing enabled on macOS: sendChanges() still appears to transmit changes immediately. But automatic fetching becomes significantly slower — often taking minutes to pick up changes from the cloud, even when new data is already available. Even manual calls to fetchChanges() behave as if they’re throttled or delayed, rather than performing an immediate fetch. Our questions: Is this delay in automatic (and post-automatic manual) fetch behavior on macOS expected, or possibly a bug? Are there specific macOS constraints that impact CKSyncEngine differently than on iOS? Once CKSyncEngine has been initialized in automatic mode, is fetchChanges() no longer treated as a truly manual trigger? Is there a recommended workaround to enable fast sync behavior on macOS — for example, by sticking to manual sync configuration and triggering sync using a CKSubscription-based mechanism when remote changes occur? Any guidance, clarification, or experiences from other developers (or Apple engineers) would be greatly appreciated — especially regarding maintaining parity between iOS and macOS sync performance. Thanks in advance!
1
1
168
Oct ’25
CloudKit console fails to query indexed records in Production
"No records found" If I create a new record on the console, I can copy the record name. I can then query for recordName and get that individual record back. BUT no other queries work. I cannot query all records. I cannot query by individual property. Just returns "no records found" Seems like my indexes got messed up. Is there a way to reset indexes on prod? This is on a coredata.cloudkit managed zone.
1
0
133
Aug ’25
Swift Data Undo
Trying to support undo & redo in an app that utilizes Swift Data and as with anything other than provided simplistic Apple demo examples the experience is not great. The problem: Im trying to build functionality that allows users to add items to an item group, where item and item group have a many-to-many relationship e.g. item group can hold many items and items can appear in multiple groups. When trying to do so with relatively simple setup of either adding or removing item group from items relationship array, I am pretty consistently met with a hard crash after performing undo & redo. Sometimes it works the first few undo & redos but 95% of the time would crash on the first one. Could not cast value of type 'Swift.Optional<Any>' (0x20a676be0) to 'Swift.Array<App.CodableStructModel>' (0x207a2bc08). Where CodableStructModel is a Codable Value type inside Item. Adding and removing this relationship should be undoable & redoable as typical for Mac interaction and is "supported" by SwiftData by default, meaning that the developer has to actively either wholly opt out of undo support in their modelContainer setup or do it on a per action scale with the only thing I know of: modelContext.processPendingChanges() modelContext.undoManager?.disableUndoRegistration() ..... modelContext.processPendingChanges() modelContext.undoManager?.enableUndoRegistration() General rant on SwiftData: Random crashes, inconsistencies, random cryptic errors thrown by the debugger and general lack of production level stability. Each update breaks something new and there is very little guidance and communication from the Swift Data team on how to adapt and more importantly consideration for developers that have adopted Swift Data. If SwiftData is not ready for production, it would go a long way to clearly communicate that and mark it as Beta product.
1
0
176
Dec ’25
defaultIsolation option and Core Data
When creating a new project in Xcode 26, the default for defaultIsolation is MainActor. Core Data creates classes for each entity using code gen, but now those classes are also internally marked as MainActor, which causes issues when accessing managed object from a background thread like this. Is there a way to fix this warning or should Xcode actually mark these auto generated classes as nonisolated to make this better? Filed as FB13840800. nonisolated struct BackgroundDataHandler { @concurrent func saveItem() async throws { let context = await PersistenceController.shared.container.newBackgroundContext() try await context.perform { let newGame = Item(context: context) newGame.timestamp = Date.now // Main actor-isolated property 'timestamp' can not be mutated from a nonisolated context; this is an error in the Swift 6 language mode try context.save() } } } Turning code gen off inside the model and creating it manually, with the nonisolated keyword, gets rid of the warning and still works fine. So I guess the auto generated class could adopt this as well? public import Foundation public import CoreData public typealias ItemCoreDataClassSet = NSSet @objc(Item) nonisolated public class Item: NSManagedObject { }
1
0
117
Jun ’25
A crash occurs when fetching history when Model has preserveValueOnDeletion attribute and using inheritance
Hello, In our app, we’ve modeled our schema using inheritance introduced in iOS 26.0, and we’re implementing SwiftData History to re-fetch models only when necessary. @Model public class Transaction { @Attribute(.preserveValueOnDeletion) public var date: Date = Date() public var amount: Double = 0 public var memo: String? } @Model public final class Spending: Transaction { public var installmentIndex: Int = 1 public var installment: Int = 1 public var installmentID: UUID? } If data has been deleted from database, we need to check a date property to determine whether to re-fetch datas. To do this, we added the preserveValueOnDeletion attribute to date property so we could retrieve it from the History tombstone value. However, after adding this attribute, a crash occurs. There is a console log Could not cast value of type 'Swift.ReferenceWritableKeyPath<Shared.ModelSchemaV5.Transaction, Foundation.Date>' (0x106bf8328) to 'Swift.PartialKeyPath<Shared.ModelSchemaV5.Spending>' (0x1094f21d8). and error log attached StrictMoneyChecking-2025-11-07-105108.txt I also tried this in the recent SampleTrip app, and fetching all history after a deletion causes the same crash. Is this issue currently being worked on or under investigation?
1
0
288
Nov ’25
'NSInvalidArgumentException', reason: 'Duplicate version checksums across stages detected.'
I have an iOS app using SwiftData with VersionedSchema. The schema is synchronized with an CloudKit container. I previously introduced some model properties that I have now removed, as they are no longer needed. This results in the current schema version being identical to one of the previous ones (except for its version number). This results in the following exception: 'NSInvalidArgumentException', reason: 'Duplicate version checksums across stages detected.' So it looks like we cannot have a newer schema version with an identical content to an older schema version. The intuitive way would be to re-add the old (identical) schema version to the end of the "schemas" list property in the SchemaMigrationPlan, in order to signal that it is the newest one, and to add a migration stage back to it, thus: public enum MySchemaMigrationPlan: SchemaMigrationPlan { public static var schemas: [any VersionedSchema.Type] { [ SchemaV100.self, SchemaV101.self, SchemaV100.self ] } public static var stages: [MigrationStage] { [ migrateV100toV101, migrateV101toV100 ] } However, I am not sure if this is the right way to go, as previously, as I wanted to write unit tests for schema migration and rollback, I tried defining an inverse for each migration stage, so that I could trigger a migration and a rollback from a unit test, which resulted in an exception saying that it is not supported to downgrade a VersionedSchema. I must admit that I solved the original problem by introducing a dummy model property that I will later remove. What would have been the correct approach?
1
0
138
Jun ’25
CloudKit - CKContainer.m:747 error
Hi everyone, Complete newbie here. Building an app and trying to use Cloudkit. I've added the CloudKit capability, triple checked the entitlements file for appropriate keys, made sure the code signing entitlements are pointing to the correct entitlements file. I've removed and cleared all of those settings and even created a new container as well as refreshed the signing. I just can't seem to figure out why I keep getting this error: Significant issue at CKContainer.m:747: In order to use CloudKit, your process must have a com.apple.developer.icloud-services entitlement. The value of this entitlement must be an array that includes the string "CloudKit" or "CloudKit-Anonymous". Any guidance is greatly appreciated.
1
0
159
Sep ’25
SwiftData Many-To-Many Relationship: Failed to fulfill link PendingRelationshipLink
Hi there, I got two models here: Two Models, with Many-To-Many Relationship @Model final class PresetParams: Identifiable { @Attribute(.unique) var id: UUID = UUID() var positionX: Float = 0.0 var positionY: Float = 0.0 var positionZ: Float = 0.0 var volume: Float = 1.0 @Relationship(deleteRule: .nullify, inverse: \Preset.presetAudioParams) var preset = [Preset]() init(position: SIMD3<Float>, volume: Float) { self.positionX = position.x self.positionY = position.y self.positionZ = position.z self.volume = volume self.preset = [] } var position: SIMD3<Float> { get { return SIMD3<Float>(x: positionX, y: positionY, z: positionZ) } set { positionX = newValue.x positionY = newValue.y positionZ = newValue.z } } } @Model final class Preset: Identifiable { @Attribute(.unique) var id: UUID = UUID() var presetName: String var presetDesc: String? var presetAudioParams = [PresetParams]() // Many-To-Many Relationship. init(presetName: String, presetDesc: String? = nil) { self.presetName = presetName self.presetDesc = presetDesc self.presetAudioParams = [] } } To be honest, I don't fully understand how the @Relationship thing works properly in a Many-To-Many relationship situation. Some tutorials suggest that it's required on the "One" side of an One-To-Many Relationship, while the "Many" side doesn't need it. And then there is an ObservableObject called "ModelActors" to manage all ModelActors, ModelContainer, etc. ModelActors, ModelContainer... class ModelActors: ObservableObject { static let shared: ModelActors = ModelActors() let sharedModelContainer: ModelContainer private init() { var schema = Schema([ // ... Preset.self, PresetParams.self, // ... ]) do { sharedModelContainer = try ModelContainer(for: schema, migrationPlan: MigrationPlan.self) } catch { fatalError("Could not create ModelContainer: \(error.localizedDescription)") } } } And there is a migrationPlan: MigrationPlan // MARK: V102 // typealias ... // MARK: V101 typealias Preset = AppSchemaV101.Preset typealias PresetParams = AppSchemaV101.PresetParams // MARK: V100 // typealias ... enum MigrationPlan: SchemaMigrationPlan { static var schemas: [VersionedSchema.Type] { [ AppSchemaV100.self, AppSchemaV101.self, AppSchemaV102.self, ] } static var stages: [MigrationStage] { [AppMigrateV100toV101, AppMigrateV101toV102] } static let AppMigrateV100toV101 = MigrationStage.lightweight(fromVersion: AppSchemaV100.self, toVersion: AppSchemaV101.self) static let AppMigrateV101toV102 = MigrationStage.lightweight(fromVersion: AppSchemaV101.self, toVersion: AppSchemaV102.self) } // MARK: Here is the AppSchemaV101 enum AppSchemaV101: VersionedSchema { static var versionIdentifier: Schema.Version = Schema.Version(1, 0, 1) static var models: [any PersistentModel.Type] { return [ // ... Preset.self, PresetParams.self ] } } Fails on iOS 18.3.x: "Failed to fulfill link PendingRelationshipLink" So I expected the SwiftData subsystem to work correctly with version control. A good news is that on iOS 18.1 it does work. But it fails on iOS 18.3.x with a fatal Error: "SwiftData/SchemaCoreData.swift:581: Fatal error: Failed to fulfill link PendingRelationshipLink(relationshipDescription: (<NSRelationshipDescription: 0x30377fe80>), name preset, isOptional 0, isTransient 0, entity PresetParams, renamingIdentifier preset, validation predicates (), warnings (), versionHashModifier (null)userInfo {}, destination entity Preset, inverseRelationship (null), minCount 0, maxCount 0, isOrdered 0, deleteRule 1, destinationEntityName: "Preset", inverseRelationshipName: Optional("presetAudioParams")), couldn't find inverse relationship 'Preset.presetAudioParams' in model" Fails on iOS 17.5: Another Error I tested it on iOS 17.5 and found another issue: Accessing or mutating the "PresetAudioParams" property causes the SwiftData Macro Codes to crash, affecting both Getter and Setter. It fails with an error: "EXC_BREAKPOINT (code=1, subcode=0x1cc1698ec)" Tweaking the @Relationship marker and ModelContainer settings didn't fix the problem.
1
0
153
Apr ’25
CloudKit, cannot deploy private database initial schema to production
We’re using a private database with a custom zone. Record types and related schema are created programmatically rather than through the dashboard. When running the app in the development environment, I can see that data is saved and can be retrieved successfully. However, in the iCloud console, I don’t see any record types or even the custom zone. Additionally, I’m unable to deploy any schema to production because no changes are detected. Do you have any ideas on what we might be missing? Installing the app from TestFlight when trying to upload a record CloudKit reports this error: <CKError 0x13f40bb10: "Invalid Arguments" (12/2006); server message = "Cannot create new type MyType in production schema" ...>
1
0
106
1d
Data Transfer or Upload to Cloudkit in Published Mode
So i created an App and for some time it was working fine. The app has features to show pdf to users without logging in. I needed to upload all data to cloudkit on public database. I was not having knowledge that there are 2 mode being a noob in coding so after i saved all records in development mode in cloudkit when i published my app, i was not able to see them (Reason because live mode works in Production mode). So i need help now to transfer data from development mode to production mode or any app or code that can help me upload all data in production mode.
1
0
139
Mar ’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
235
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
134
Jun ’25
SwiftData @Model: Optional to-many relationship is never nil at runtime
Hi all, I’m trying to understand SwiftData’s runtime semantics around optional to-many relationships, especially in the context of CloudKit-backed models. I ran into behavior that surprised me, and I’d like to confirm whether this is intended design or a potential issue / undocumented behavior. Minimal example import SwiftUI import SwiftData @Model class Node { var children: [Node]? = nil var parent: Node? = nil init(children: [Node]? = nil, parent: Node? = nil) { self.children = children self.parent = parent print(self.children == nil) } } struct ContentView: View { var body: some View { Button("Create") { _ = Node(children: nil) } } } Observed behavior If @Model is not used, children == nil prints true as expected. If @Model is used, children == nil prints false. Inspecting the macro expansion, it appears SwiftData initializes relationship storage using backing data placeholders and normalizes to-many relationships into empty collections at runtime, even when declared as optional. CloudKit context From the SwiftData + CloudKit documentation: “The iCloud servers don’t guarantee atomic processing of relationship changes, so CloudKit requires all relationships to be optional.” Because of this, modeling relationships as optional is required when syncing with CloudKit, even for to-many relationships. This is why I’m hesitant to simply switch the model to a non-optional [Node] = [], even though that would match the observed runtime behavior. Questions Is it intentional that optional to-many relationships in SwiftData are never nil at runtime, and instead materialize as empty collections? If so, is Optional<[Model]> effectively treated as [Model] for runtime access, despite being required for CloudKit compatibility? Is the defaultValue: nil in the generated Schema.PropertyMetadata intended only for schema/migration purposes rather than representing a possible runtime state? Is there a recommended modeling pattern for CloudKit-backed SwiftData models where relationships must be optional, but runtime semantics behave as non-optional? I’m mainly looking to ensure I’m aligning with SwiftData’s intended design and not relying on behavior that could change or break with CloudKit sync. Thanks in advance for any clarification!
1
1
366
Jan ’26
SwiftData migration crashes when working with relationships
The following complex migration consistently crashes the app with the following error: SwiftData/PersistentModel.swift:726: Fatal error: What kind of backing data is this? SwiftData._KKMDBackingData<SwiftDataMigration.ItemSchemaV1.ItemList> My app relies on a complex migration that involves these optional 1 to n relationships. Theoretically I could not assign the relationships in the willMigrate block but afterwards I am not able to tell which list and items belonged together. Steps to reproduce: Run project Change typealias CurrentSchema to ItemSchemaV2 instead of ItemSchemaV1. Run project again -> App crashes My setup: Xcode Version 16.2 (16C5032a) MacOS Sequoia 15.4 iPhone 12 with 18.3.2 (22D82) Am I doing something wrong or did I stumble upon a bug? I have a demo Xcode project ready but I could not upload it here so I put the code below. Thanks for your help typealias CurrentSchema = ItemSchemaV1 typealias ItemList = CurrentSchema.ItemList typealias Item = CurrentSchema.Item @main struct SwiftDataMigrationApp: App { var sharedModelContainer: ModelContainer = { do { return try ModelContainer(for: ItemList.self, migrationPlan: MigrationPlan.self) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } This is the migration plan enum MigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [ItemSchemaV1.self, ItemSchemaV2.self] } static var stages: [MigrationStage] = [ MigrationStage.custom(fromVersion: ItemSchemaV1.self, toVersion: ItemSchemaV2.self, willMigrate: { context in print("Started migration") let oldlistItems = try context.fetch(FetchDescriptor<ItemSchemaV1.ItemList>()) for list in oldlistItems { let items = list.items.map { ItemSchemaV2.Item(timestamp: $0.timestamp)} let newList = ItemSchemaV2.ItemList(items: items, name: list.name, note: "This is a new property") context.insert(newList) context.delete(list) } try context.save() // Crash indicated here print("Finished willMigrate") }, didMigrate: { context in print("Did migrate successfully") }) ] } The versioned schemas enum ItemSchemaV1: VersionedSchema { static var versionIdentifier = Schema.Version(1, 0, 0) static var models: [any PersistentModel.Type] { [Item.self] } @Model final class Item { var timestamp: Date var list: ItemSchemaV1.ItemList? init(timestamp: Date) { self.timestamp = timestamp } } @Model final class ItemList { @Relationship(deleteRule: .cascade, inverse: \ItemSchemaV1.Item.list) var items: [Item] var name: String init(items: [Item], name: String) { self.items = items self.name = name } } } enum ItemSchemaV2: VersionedSchema { static var versionIdentifier = Schema.Version(2, 0, 0) static var models: [any PersistentModel.Type] { [Item.self] } @Model final class Item { var timestamp: Date var list: ItemSchemaV2.ItemList? init(timestamp: Date) { self.timestamp = timestamp } } @Model final class ItemList { @Relationship(deleteRule: .cascade, inverse: \ItemSchemaV2.Item.list) var items: [Item] var name: String var note: String init(items: [Item], name: String, note: String = "") { self.items = items self.name = name self.note = note } } } Last the ContentView: struct ContentView: View { @Query private var itemLists: [ItemList] var body: some View { NavigationSplitView { List { ForEach(itemLists) { list in NavigationLink { List(list.items) { item in Text(item.timestamp.formatted(date: .abbreviated, time: .complete)) } .navigationTitle(list.name) } label: { Text(list.name) } } } .navigationTitle("Crashing migration demo") .onAppear { if itemLists.isEmpty { for index in 0..<10 { let items = [Item(timestamp: Date.now)] let listItem = ItemList(items: items, name: "List No. \(index)") modelContext.insert(listItem) } try! modelContext.save() } } } detail: { Text("Select an item") } } }
Replies
1
Boosts
1
Views
182
Activity
Apr ’25
Login issues on CloudKit Console
Hi everyone In the last 24 hours, I’ve been running into some issues with the CloudKit console. Most of the time, I‘ll get an error stating an error has caused this web page to stop working correctly. Reloading doesn’t fix the issue, nor does using different browsers: Today I’ve got another error, something along the lines of the Console not being able to fetch the teams I’m assigned to and an XHF error pop-up. Has anyone encountered the same issues? After trying multiple times, I’m able to reach my database but it’s a bit frustrating as it’s very unreliable this way. Thanks for your feedback! Dave
Replies
1
Boosts
3
Views
135
Activity
May ’25
Best practice for centralizing SwiftData query logic and actions in an @Observable manager?
I'm building a SwiftUI app with SwiftData and want to centralize both query logic and related actions in a manager class. For example, let's say I have a reading app where I need to track the currently reading book across multiple views. What I want to achieve: @Observable class ReadingManager { let modelContext: ModelContext // Ideally, I'd love to do this: @Query(filter: #Predicate<Book> { $0.isCurrentlyReading }) var currentBooks: [Book] // ❌ But @Query doesn't work here var currentBook: Book? { currentBooks.first } func startReading(_ book: Book) { // Stop current book if any if let current = currentBook { current.isCurrentlyReading = false } book.isCurrentlyReading = true try? modelContext.save() } func stopReading() { currentBook?.isCurrentlyReading = false try? modelContext.save() } } // Then use it cleanly in any view: struct BookRow: View { @Environment(ReadingManager.self) var manager let book: Book var body: some View { Text(book.title) Button("Start Reading") { manager.startReading(book) } if manager.currentBook == book { Text("Currently Reading") } } } The problem is @Query only works in SwiftUI views. Without the manager, I'd need to duplicate the same query in every view just to call these common actions. Is there a recommended pattern for this? Or should I just accept query duplication across views as the intended SwiftUI/SwiftData approach?
Replies
1
Boosts
0
Views
402
Activity
Jan ’26
Core Data crash while trying to merge
I'm looking for guidance how to mitigate this crash. It seems super deep inside Core Data' FRC fetchedObjects management. In my code, it's initiated by this viewContext.perform { [unowned self] in self.viewContext.mergeChanges(fromContextDidSave: notification) } which is directly followed by the stack trace below. Basically merging data from .NSManagedObjectContextDidSave notification from another NSManagedObjectContext. Nothing special, it works great for years, apart from these rare occurrences. Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Reason: -[__NSCFArray objectAtIndex:]: index (235) beyond bounds (234) Termination Reason: SIGNAL 6 Abort trap: 6 Triggered by Thread: 0 Last Exception Backtrace: 0 CoreFoundation 0x199e947cc __exceptionPreprocess + 164 (NSException.m:249) 1 libobjc.A.dylib 0x1971672e4 objc_exception_throw + 88 (objc-exception.mm:356) 2 CoreFoundation 0x199fc4258 _NSArrayRaiseBoundException + 368 (NSCFArray.m:22) 3 CoreFoundation 0x199e288a4 -[__NSCFArray objectAtIndex:] + 200 (NSCFArray.m:42) 4 CoreData 0x1a1e17338 -[_PFMutableProxyArray objectAtIndex:] + 40 (_PFArray.m:1860) 5 CoreData 0x1a1e1673c -[NSFetchedResultsController _updateFetchedObjectsWithInsertChange:] + 380 (NSFetchedResultsController.m:1582) 6 CoreData 0x1a1e1426c __82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 2240 (NSFetchedResultsController.m:2171) 7 CoreData 0x1a1dcdf80 developerSubmittedBlockToNSManagedObjectContextPerform + 156 (NSManagedObjectContext.m:4002) 8 CoreData 0x1a1e41a44 -[NSManagedObjectContext performBlockAndWait:] + 216 (NSManagedObjectContext.m:4113) 9 CoreData 0x1a1e41034 -[NSFetchedResultsController _core_managedObjectContextDidChange:] + 124 (NSFetchedResultsController.m:2379) 10 CoreFoundation 0x199e632f4 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 148 (CFNotificationCenter.c:701) 11 CoreFoundation 0x199e63210 ___CFXRegistrationPost_block_invoke + 88 (CFNotificationCenter.c:194) 12 CoreFoundation 0x199e63158 _CFXRegistrationPost + 436 (CFNotificationCenter.c:222) 13 CoreFoundation 0x199e6170c _CFXNotificationPost + 728 (CFNotificationCenter.c:1248) 14 Foundation 0x198a84ea4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 92 (NSNotification.m:531) 15 CoreData 0x1a1e11650 -[NSManagedObjectContext _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1736 (NSManagedObjectContext.m:8098) 16 CoreData 0x1a1e10e0c -[NSManagedObjectContext _postRefreshedObjectsNotificationAndClearList] + 164 (NSManagedObjectContext.m:7631) 17 CoreData 0x1a1e0fad8 -[NSManagedObjectContext _processRecentChanges:] + 100 (NSManagedObjectContext.m:7714) 18 CoreData 0x1a1e3563c -[NSManagedObjectContext _coreMergeChangesFromDidSaveDictionary:usingObjectIDs:withClientQueryGeneration:] + 3436 (NSManagedObjectContext.m:3723) 19 CoreData 0x1a1e34350 __116+[NSManagedObjectContext(_NSCoreDataSPI) _mergeChangesFromRemoteContextSave:intoContexts:withClientQueryGeneration:]_block_invoke_4 + 76 (NSManagedObjectContext.m:9531) 20 CoreData 0x1a1dcdf80 developerSubmittedBlockToNSManagedObjectContextPerform + 156 (NSManagedObjectContext.m:4002) 21 CoreData 0x1a1e41a44 -[NSManagedObjectContext performBlockAndWait:] + 216 (NSManagedObjectContext.m:4113) 22 CoreData 0x1a1e39880 +[NSManagedObjectContext _mergeChangesFromRemoteContextSave:intoContexts:withClientQueryGeneration:] + 2372 (NSManagedObjectContext.m:9537) 23 CoreData 0x1a1e344a0 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 292 (NSManagedObjectContext.m:0)
Replies
1
Boosts
0
Views
75
Activity
Apr ’25
CKSyncEngine on macOS: Automatic Fetch Extremely Slow Compared to iOS
Hi everyone, We’re currently using CKSyncEngine to sync all our locally persisted data across user devices (iOS and macOS) via iCloud. We’ve noticed something strange and reproducible: On iOS, when the CKSyncEngine is initialized with manual sync behavior, both manual calls to fetchChanges() and sendChanges() happen nearly instantly (usually within seconds). Automatic syncing is also very fast. On macOS, when the CKSyncEngine is initialized with manual sync behavior, fetchChanges() and sendChanges() are also fast and responsive. However, once CKSyncEngine is initialized with automatic syncing enabled on macOS: sendChanges() still appears to transmit changes immediately. But automatic fetching becomes significantly slower — often taking minutes to pick up changes from the cloud, even when new data is already available. Even manual calls to fetchChanges() behave as if they’re throttled or delayed, rather than performing an immediate fetch. Our questions: Is this delay in automatic (and post-automatic manual) fetch behavior on macOS expected, or possibly a bug? Are there specific macOS constraints that impact CKSyncEngine differently than on iOS? Once CKSyncEngine has been initialized in automatic mode, is fetchChanges() no longer treated as a truly manual trigger? Is there a recommended workaround to enable fast sync behavior on macOS — for example, by sticking to manual sync configuration and triggering sync using a CKSubscription-based mechanism when remote changes occur? Any guidance, clarification, or experiences from other developers (or Apple engineers) would be greatly appreciated — especially regarding maintaining parity between iOS and macOS sync performance. Thanks in advance!
Replies
1
Boosts
1
Views
168
Activity
Oct ’25
CloudKit console fails to query indexed records in Production
"No records found" If I create a new record on the console, I can copy the record name. I can then query for recordName and get that individual record back. BUT no other queries work. I cannot query all records. I cannot query by individual property. Just returns "no records found" Seems like my indexes got messed up. Is there a way to reset indexes on prod? This is on a coredata.cloudkit managed zone.
Replies
1
Boosts
0
Views
133
Activity
Aug ’25
Swift Data Undo
Trying to support undo & redo in an app that utilizes Swift Data and as with anything other than provided simplistic Apple demo examples the experience is not great. The problem: Im trying to build functionality that allows users to add items to an item group, where item and item group have a many-to-many relationship e.g. item group can hold many items and items can appear in multiple groups. When trying to do so with relatively simple setup of either adding or removing item group from items relationship array, I am pretty consistently met with a hard crash after performing undo & redo. Sometimes it works the first few undo & redos but 95% of the time would crash on the first one. Could not cast value of type 'Swift.Optional<Any>' (0x20a676be0) to 'Swift.Array<App.CodableStructModel>' (0x207a2bc08). Where CodableStructModel is a Codable Value type inside Item. Adding and removing this relationship should be undoable & redoable as typical for Mac interaction and is "supported" by SwiftData by default, meaning that the developer has to actively either wholly opt out of undo support in their modelContainer setup or do it on a per action scale with the only thing I know of: modelContext.processPendingChanges() modelContext.undoManager?.disableUndoRegistration() ..... modelContext.processPendingChanges() modelContext.undoManager?.enableUndoRegistration() General rant on SwiftData: Random crashes, inconsistencies, random cryptic errors thrown by the debugger and general lack of production level stability. Each update breaks something new and there is very little guidance and communication from the Swift Data team on how to adapt and more importantly consideration for developers that have adopted Swift Data. If SwiftData is not ready for production, it would go a long way to clearly communicate that and mark it as Beta product.
Replies
1
Boosts
0
Views
176
Activity
Dec ’25
defaultIsolation option and Core Data
When creating a new project in Xcode 26, the default for defaultIsolation is MainActor. Core Data creates classes for each entity using code gen, but now those classes are also internally marked as MainActor, which causes issues when accessing managed object from a background thread like this. Is there a way to fix this warning or should Xcode actually mark these auto generated classes as nonisolated to make this better? Filed as FB13840800. nonisolated struct BackgroundDataHandler { @concurrent func saveItem() async throws { let context = await PersistenceController.shared.container.newBackgroundContext() try await context.perform { let newGame = Item(context: context) newGame.timestamp = Date.now // Main actor-isolated property 'timestamp' can not be mutated from a nonisolated context; this is an error in the Swift 6 language mode try context.save() } } } Turning code gen off inside the model and creating it manually, with the nonisolated keyword, gets rid of the warning and still works fine. So I guess the auto generated class could adopt this as well? public import Foundation public import CoreData public typealias ItemCoreDataClassSet = NSSet @objc(Item) nonisolated public class Item: NSManagedObject { }
Replies
1
Boosts
0
Views
117
Activity
Jun ’25
A crash occurs when fetching history when Model has preserveValueOnDeletion attribute and using inheritance
Hello, In our app, we’ve modeled our schema using inheritance introduced in iOS 26.0, and we’re implementing SwiftData History to re-fetch models only when necessary. @Model public class Transaction { @Attribute(.preserveValueOnDeletion) public var date: Date = Date() public var amount: Double = 0 public var memo: String? } @Model public final class Spending: Transaction { public var installmentIndex: Int = 1 public var installment: Int = 1 public var installmentID: UUID? } If data has been deleted from database, we need to check a date property to determine whether to re-fetch datas. To do this, we added the preserveValueOnDeletion attribute to date property so we could retrieve it from the History tombstone value. However, after adding this attribute, a crash occurs. There is a console log Could not cast value of type 'Swift.ReferenceWritableKeyPath<Shared.ModelSchemaV5.Transaction, Foundation.Date>' (0x106bf8328) to 'Swift.PartialKeyPath<Shared.ModelSchemaV5.Spending>' (0x1094f21d8). and error log attached StrictMoneyChecking-2025-11-07-105108.txt I also tried this in the recent SampleTrip app, and fetching all history after a deletion causes the same crash. Is this issue currently being worked on or under investigation?
Replies
1
Boosts
0
Views
288
Activity
Nov ’25
'NSInvalidArgumentException', reason: 'Duplicate version checksums across stages detected.'
I have an iOS app using SwiftData with VersionedSchema. The schema is synchronized with an CloudKit container. I previously introduced some model properties that I have now removed, as they are no longer needed. This results in the current schema version being identical to one of the previous ones (except for its version number). This results in the following exception: 'NSInvalidArgumentException', reason: 'Duplicate version checksums across stages detected.' So it looks like we cannot have a newer schema version with an identical content to an older schema version. The intuitive way would be to re-add the old (identical) schema version to the end of the "schemas" list property in the SchemaMigrationPlan, in order to signal that it is the newest one, and to add a migration stage back to it, thus: public enum MySchemaMigrationPlan: SchemaMigrationPlan { public static var schemas: [any VersionedSchema.Type] { [ SchemaV100.self, SchemaV101.self, SchemaV100.self ] } public static var stages: [MigrationStage] { [ migrateV100toV101, migrateV101toV100 ] } However, I am not sure if this is the right way to go, as previously, as I wanted to write unit tests for schema migration and rollback, I tried defining an inverse for each migration stage, so that I could trigger a migration and a rollback from a unit test, which resulted in an exception saying that it is not supported to downgrade a VersionedSchema. I must admit that I solved the original problem by introducing a dummy model property that I will later remove. What would have been the correct approach?
Replies
1
Boosts
0
Views
138
Activity
Jun ’25
CloudKit - CKContainer.m:747 error
Hi everyone, Complete newbie here. Building an app and trying to use Cloudkit. I've added the CloudKit capability, triple checked the entitlements file for appropriate keys, made sure the code signing entitlements are pointing to the correct entitlements file. I've removed and cleared all of those settings and even created a new container as well as refreshed the signing. I just can't seem to figure out why I keep getting this error: Significant issue at CKContainer.m:747: In order to use CloudKit, your process must have a com.apple.developer.icloud-services entitlement. The value of this entitlement must be an array that includes the string "CloudKit" or "CloudKit-Anonymous". Any guidance is greatly appreciated.
Replies
1
Boosts
0
Views
159
Activity
Sep ’25
Can't sign in to Apple in Tahoe VM
Running Tahoe 26.1 in a virtual machine, I can't sign into my Apple account. There is an error message saying "Could not communicate with the server." Internet access otherwise seems to be working in the VM. I tried both UTM and VirtualBuddy. Is this supposed to work?
Replies
1
Boosts
0
Views
328
Activity
Dec ’25
SwiftData Many-To-Many Relationship: Failed to fulfill link PendingRelationshipLink
Hi there, I got two models here: Two Models, with Many-To-Many Relationship @Model final class PresetParams: Identifiable { @Attribute(.unique) var id: UUID = UUID() var positionX: Float = 0.0 var positionY: Float = 0.0 var positionZ: Float = 0.0 var volume: Float = 1.0 @Relationship(deleteRule: .nullify, inverse: \Preset.presetAudioParams) var preset = [Preset]() init(position: SIMD3<Float>, volume: Float) { self.positionX = position.x self.positionY = position.y self.positionZ = position.z self.volume = volume self.preset = [] } var position: SIMD3<Float> { get { return SIMD3<Float>(x: positionX, y: positionY, z: positionZ) } set { positionX = newValue.x positionY = newValue.y positionZ = newValue.z } } } @Model final class Preset: Identifiable { @Attribute(.unique) var id: UUID = UUID() var presetName: String var presetDesc: String? var presetAudioParams = [PresetParams]() // Many-To-Many Relationship. init(presetName: String, presetDesc: String? = nil) { self.presetName = presetName self.presetDesc = presetDesc self.presetAudioParams = [] } } To be honest, I don't fully understand how the @Relationship thing works properly in a Many-To-Many relationship situation. Some tutorials suggest that it's required on the "One" side of an One-To-Many Relationship, while the "Many" side doesn't need it. And then there is an ObservableObject called "ModelActors" to manage all ModelActors, ModelContainer, etc. ModelActors, ModelContainer... class ModelActors: ObservableObject { static let shared: ModelActors = ModelActors() let sharedModelContainer: ModelContainer private init() { var schema = Schema([ // ... Preset.self, PresetParams.self, // ... ]) do { sharedModelContainer = try ModelContainer(for: schema, migrationPlan: MigrationPlan.self) } catch { fatalError("Could not create ModelContainer: \(error.localizedDescription)") } } } And there is a migrationPlan: MigrationPlan // MARK: V102 // typealias ... // MARK: V101 typealias Preset = AppSchemaV101.Preset typealias PresetParams = AppSchemaV101.PresetParams // MARK: V100 // typealias ... enum MigrationPlan: SchemaMigrationPlan { static var schemas: [VersionedSchema.Type] { [ AppSchemaV100.self, AppSchemaV101.self, AppSchemaV102.self, ] } static var stages: [MigrationStage] { [AppMigrateV100toV101, AppMigrateV101toV102] } static let AppMigrateV100toV101 = MigrationStage.lightweight(fromVersion: AppSchemaV100.self, toVersion: AppSchemaV101.self) static let AppMigrateV101toV102 = MigrationStage.lightweight(fromVersion: AppSchemaV101.self, toVersion: AppSchemaV102.self) } // MARK: Here is the AppSchemaV101 enum AppSchemaV101: VersionedSchema { static var versionIdentifier: Schema.Version = Schema.Version(1, 0, 1) static var models: [any PersistentModel.Type] { return [ // ... Preset.self, PresetParams.self ] } } Fails on iOS 18.3.x: "Failed to fulfill link PendingRelationshipLink" So I expected the SwiftData subsystem to work correctly with version control. A good news is that on iOS 18.1 it does work. But it fails on iOS 18.3.x with a fatal Error: "SwiftData/SchemaCoreData.swift:581: Fatal error: Failed to fulfill link PendingRelationshipLink(relationshipDescription: (<NSRelationshipDescription: 0x30377fe80>), name preset, isOptional 0, isTransient 0, entity PresetParams, renamingIdentifier preset, validation predicates (), warnings (), versionHashModifier (null)userInfo {}, destination entity Preset, inverseRelationship (null), minCount 0, maxCount 0, isOrdered 0, deleteRule 1, destinationEntityName: "Preset", inverseRelationshipName: Optional("presetAudioParams")), couldn't find inverse relationship 'Preset.presetAudioParams' in model" Fails on iOS 17.5: Another Error I tested it on iOS 17.5 and found another issue: Accessing or mutating the "PresetAudioParams" property causes the SwiftData Macro Codes to crash, affecting both Getter and Setter. It fails with an error: "EXC_BREAKPOINT (code=1, subcode=0x1cc1698ec)" Tweaking the @Relationship marker and ModelContainer settings didn't fix the problem.
Replies
1
Boosts
0
Views
153
Activity
Apr ’25
SwiftData CloudKit hangs on Active scene Phase
If Cloudkit is enabled, SwiftData @Query operation hangs when the View scenePhase becomes active. Seems like the more @Query calls you have, the more it hangs. This has been first documented some time ago, but in typical Apple style, it has not been addressed or even commented on. https://developer.apple.com/forums/thread/761434
Replies
1
Boosts
0
Views
211
Activity
Aug ’25
CloudKit, cannot deploy private database initial schema to production
We’re using a private database with a custom zone. Record types and related schema are created programmatically rather than through the dashboard. When running the app in the development environment, I can see that data is saved and can be retrieved successfully. However, in the iCloud console, I don’t see any record types or even the custom zone. Additionally, I’m unable to deploy any schema to production because no changes are detected. Do you have any ideas on what we might be missing? Installing the app from TestFlight when trying to upload a record CloudKit reports this error: <CKError 0x13f40bb10: "Invalid Arguments" (12/2006); server message = "Cannot create new type MyType in production schema" ...>
Replies
1
Boosts
0
Views
106
Activity
1d
Data Transfer or Upload to Cloudkit in Published Mode
So i created an App and for some time it was working fine. The app has features to show pdf to users without logging in. I needed to upload all data to cloudkit on public database. I was not having knowledge that there are 2 mode being a noob in coding so after i saved all records in development mode in cloudkit when i published my app, i was not able to see them (Reason because live mode works in Production mode). So i need help now to transfer data from development mode to production mode or any app or code that can help me upload all data in production mode.
Replies
1
Boosts
0
Views
139
Activity
Mar ’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!
Replies
1
Boosts
0
Views
235
Activity
Jun ’25
Sharing SwiftData between two apps
This is probably super simple answer that I missed, but: I have an app that has a database; I'd like to create a second app (actually a CLI tool), and access the same database. Is that possible? And, if so, how? 😄
Replies
1
Boosts
0
Views
383
Activity
Jan ’26
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?
Replies
1
Boosts
0
Views
134
Activity
Jun ’25
SwiftData @Model: Optional to-many relationship is never nil at runtime
Hi all, I’m trying to understand SwiftData’s runtime semantics around optional to-many relationships, especially in the context of CloudKit-backed models. I ran into behavior that surprised me, and I’d like to confirm whether this is intended design or a potential issue / undocumented behavior. Minimal example import SwiftUI import SwiftData @Model class Node { var children: [Node]? = nil var parent: Node? = nil init(children: [Node]? = nil, parent: Node? = nil) { self.children = children self.parent = parent print(self.children == nil) } } struct ContentView: View { var body: some View { Button("Create") { _ = Node(children: nil) } } } Observed behavior If @Model is not used, children == nil prints true as expected. If @Model is used, children == nil prints false. Inspecting the macro expansion, it appears SwiftData initializes relationship storage using backing data placeholders and normalizes to-many relationships into empty collections at runtime, even when declared as optional. CloudKit context From the SwiftData + CloudKit documentation: “The iCloud servers don’t guarantee atomic processing of relationship changes, so CloudKit requires all relationships to be optional.” Because of this, modeling relationships as optional is required when syncing with CloudKit, even for to-many relationships. This is why I’m hesitant to simply switch the model to a non-optional [Node] = [], even though that would match the observed runtime behavior. Questions Is it intentional that optional to-many relationships in SwiftData are never nil at runtime, and instead materialize as empty collections? If so, is Optional<[Model]> effectively treated as [Model] for runtime access, despite being required for CloudKit compatibility? Is the defaultValue: nil in the generated Schema.PropertyMetadata intended only for schema/migration purposes rather than representing a possible runtime state? Is there a recommended modeling pattern for CloudKit-backed SwiftData models where relationships must be optional, but runtime semantics behave as non-optional? I’m mainly looking to ensure I’m aligning with SwiftData’s intended design and not relying on behavior that could change or break with CloudKit sync. Thanks in advance for any clarification!
Replies
1
Boosts
1
Views
366
Activity
Jan ’26