SwiftData

RSS for tag

Learn to write model code declaratively to add managed persistence and efficient model fetching.

SwiftData Documentation

Posts under SwiftData subtopic

Post

Replies

Boosts

Views

Activity

Handling SwiftData Initialization Errors
The traditional way to initialize a SwiftData app looks like some variation of the following: @main struct TrainingCornerApp: App { let dbSchema: Schema = ... init() { } var body: some Scene { WindowGroup { MainAppScreen() .modelContainer(modelContainer) } } } private var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false, cloudKitDatabase: .automatic) do { container = try ModelContainer(for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) } catch { fatalError("Failed to create model container: \(error.localizedDescription)") } return container } } That is, if creating the modelContainer fails, the app aborts with a fatalError. What I want to do is have the application present an alert message for the user before terminating. (Let the user know the app can't run and suggest how to get help -- that sort of thing.) However, I've been having a hard time getting this to work, and it seems that the problems are related to trying to generate the alert at such an early stage in app startup. Does anyone have ideas/suggestions on how I might do this?
0
0
87
4d
SwiftData public sharing
I have an Apple app that uses SwiftData and icloud to sync the App's data across users' devices. Everything is working well. However, I am facing the following issue: SwiftData does not support public sharing of the object graph with other users via iCloud. How can I overcome this limitation without stopping using SwiftData? Thanks in advance!
3
7
875
4d
Best practices
Hi everyone, I'm Alexsander. My friends call me Lexie. I have been working as software developer since 6 years ago, I have a lot of experience with Java and I started working with Angular since the last year. I am new in the Apple ecosystem and I have a question about best practices in full native Swift apps. There is any source (blogs, youtube channels, books, et al.) where I can understand the best practices? Like, I've heard about MVVM to scalable apps but I don't know exactly how to apply it. I think it's because usually I do not have my front-end components in the same project of my backend. I've been watching some videos from Apple Developer youtube channel and they are absolutely amazing, but they only keep teaching people to use the "raw" resources, not matching with the best practices. For example, I saw using swift data we do not need to write any SQL Query, unlike Java Ecossystem where even we use a ORM we usually write our queries natively, whether creating a table or fetching data.
2
0
572
6d
SwiftData query returns "private" string in WidgetExtension
Hello, I am trying to set up Widgets in my app. I want to fetch my data in the SwiftData container that is shared between my app and my WidgetExtension with App Group. let modelContext = ModelContext(modelContainer) let predicate = #Predicate<Test>{ return $0.attribute == true } return try modelContext.fetch(FetchDescriptor (predicate: predicate, sortBy: [SortDescriptor(\Test.name)])) When this code is run in my WidgetExtension, returned objects attributes values are replaced with "" string. In the logs, Swift Data writes Query returned unrequested identifiers that have been dropped: <private> Any idea what I might be doing wrong to share my SwiftData between my App and my Widget? App Groups capability has been added to both apps and extension with the same identifier. Thank you
2
0
415
3w
SwiftData Decimal loses precision after save/fetch with a minimal reproduction
I believe I may have found a SwiftData persistence bug, but I'd like to verify that I'm not overlooking a documented limitation before filing Feedback. This minimal example appears to lose precision when persisting a Decimal: import Foundation import SwiftData @Model class Item { var value: Decimal init(_ value: Decimal) { self.value = value } } let original = Decimal(string: "123456789012345.6")! let container = try ModelContainer( for: Item.self, configurations: .init(isStoredInMemoryOnly: true) ) let context = ModelContext(container) context.insert(Item(original)) try context.save() let fetched = try ModelContext(container) .fetch(FetchDescriptor<Item>()) .first! print(original) print(fetched.value) Output: 123456789012345.6 123456789012346 A few observations from additional testing: Decimal(string:) preserves the value before persistence. Decimal ↔ NSDecimalNumber bridging preserves the value in separate tests. The value remains exact after model initialization, insertion, and save() on the registered object. The first Swift-visible precision loss appears after fetching from a new ModelContext. As a control, I repeated the test using Core Data with an NSInMemoryStoreType store and an NSDecimalAttributeType attribute. That round-tripped the tested values exactly. Inspecting the SQLite store generated by SwiftData showed the affected value stored as a REAL. At this point it appears the precision loss occurs somewhere in the SwiftData/Core Data persistence pipeline rather than in Decimal itself. Can anyone reproduce this, or is there a documented limitation on Decimal persistence in SwiftData that I have missed? If this is expected behavior, what is the recommended way to persist exact decimal values for financial applications?
0
0
362
3w
SwiftData Decimal loses precision after save/fetch with a minimal reproduction
I believe I may have found a SwiftData persistence bug, but I'd like to verify that I'm not overlooking a documented limitation before filing Feedback. This minimal example appears to lose precision when persisting a Decimal: import Foundation import SwiftData @Model class Item { var value: Decimal init(_ value: Decimal) { self.value = value } } let original = Decimal(string: "123456789012345.6")! let container = try ModelContainer( for: Item.self, configurations: .init(isStoredInMemoryOnly: true) ) let context = ModelContext(container) context.insert(Item(original)) try context.save() let fetched = try ModelContext(container) .fetch(FetchDescriptor<Item>()) .first! print(original) print(fetched.value) Output: 123456789012345.6 123456789012346 A few observations from additional testing: Decimal(string:) preserves the value before persistence. Decimal ↔ NSDecimalNumber bridging preserves the value in separate tests. The value remains exact after model initialization, insertion, and save() on the registered object. The first Swift-visible precision loss appears after fetching from a new ModelContext. As a control, I repeated the test using Core Data with an NSInMemoryStoreType store and an NSDecimalAttributeType attribute. That round-tripped the tested values exactly. Inspecting the SQLite store generated by SwiftData showed the affected value stored as a REAL. At this point it appears the precision loss occurs somewhere in the SwiftData/Core Data persistence pipeline rather than in Decimal itself. Can anyone reproduce this, or is there a documented limitation on Decimal persistence in SwiftData that I have missed? If this is expected behavior, what is the recommended way to persist exact decimal values for financial applications?
0
0
353
3w
SwiftData Model didset
Hi, I'm trying out new SwiftData in a small Xcode project. It seems that the property observers didSet and willSet don't work anymore for swift data anymore. In code like this, the didSet does nothing and seems to never be called. @Model public final class importConfig: Identifiable, ObservableObject{ @Attribute(.unique) public var id: UUID /// Name of the configuration var configName: String /// Numbers App document to open var numbersFilePath: URL? /// Indicate wether current <numbersFilePath> Numbers App document has been loaded and analyzed var isLoaded: Bool = false /// Current selected sheet var selectedSheetID: UUID? { didSet { selectedSheetID = nil print("test") } } } Am I doing something wrong or is it the expected behavior ? If it is the expected behavior, how can I add "business" rules when setting/unsetting value to model properties ? I tried to add rules directly with .onchange() in my views, but this way I have to repeat the same rules/code. Is there any alternative to do so ? Thank you
3
1
2.1k
Jul ’26
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?
4
0
1.5k
Jun ’26
Prevent SwiftData Upserts
Following the premise that database integrity should be handled by rules in the schema as much as possible, the automatic UPSERT whereby trying to create a record with the same unique key as a record that already exists does not trigger an INSERT error but automatically updates the existing record is pretty alien. I really don't want to enforce this on business logic and I want the backend to do the work. Is there away to prevent the UPSERT?
0
0
650
Jun ’26
Under what circumstances does @Query call body?
Hi I was wondering under what circumstances does @Query call body. Does it call it when the result set changes? E.g. object added/removed/moved. Does it also call when the result set is the same but a property of a model changed? I'd prefer 1, since models are @Observable my Views can handle tracking if they need to update when a property of a model changes. But I am concerned it is 2 which would cause unnecessary calls to body? E.g. a ForEach would needlessly be reinit since the model array is exactly the same. So which is it? By the way it would be useful if the docs could be updated with this important info. Thanks
1
0
704
Jun ’26
SwiftData, CloudKit and 2 AppleIDs
I have a SwiftData app that runs on iOS, iPadOS, and MacCatalyst and which uses CloudKit for inter-device sync. Unfortunately, I also have two AppleIDs (which I 'll refer to as OLDID and NEWID). Although all three devices (phone, pad and desktop) are currently set up with NEWID as the active AppleID, during development and testing, my desktop Mac used OLDID. Apparently, the system remembers the AppleID to use with each CloudKit app (based on the AppleID active at time of first use), because the desktop app and the mobile apps apparently sync to different AppleID accounts. I can delete the local database on the desktop and delete the local app on the mobile devices and in each case, reloading/rerunning the app causes the respective databases to be restored from the cloud. The two mobile devices sync with each other, but not with the desktop; the desktop doesn't sync with either device. And the two databases have decidedly different contents. My goal is to consolidate everything so that there is one database, shared and synced between desktop, pad, phone and cloud. I presume that there is a setting somewhere (but clearly NOT in the app's sandboxed container) that specifies what iCloud account to use for that (and each) app. Note: I have other apps which sync between all my devices, so the setting must be on a per-app basis. I also presume that if I changed it's value on my desktop (so that all three devices used the same AppleID for cloud services for my app), that the content of the local database on my desktop would be synced automatically to the NEWID cloud account and then (also automatically) synchronized with my mobile devices. I.e., I speculate that I can solve all my problems by changing that setting on my desktop Mac. So I have two questions: Is all this correct? How do I make this setting change. (I.e., where is it and how do I change it) Does anyone have any experience and can help with this issue? Thanks
3
0
827
Jun ’26
SwiftData predicate filtered by enum case
I have several Swift Data types with a property of type enum. Whenever I've tried to write a predicate returning data objects only of a certain enum case, the compiler throws an error from the macro at build time. (which I don't have handy, sorry...). Is this supported? And if so, how would you write the predicate? @Model public final class AlbumList { // ... public var listType: AlbumListType // ... } public enum AlbumListType: String, CaseIterable, Codable { case listener case dj }
5
2
924
Jun ’26
Delay when using ResultsObserver over @Query?
I was testing how to use ResultsObserver on a ViewModel in SwiftData. In Xcode 27, Developer v1, I have the following view import SwiftUI import SwiftData @Model class TaskItem { var name: String var priority: Int init(name: String, priority: Int) { self.name = name self.priority = priority } } @Observable @MainActor class RandomViewModel { let observer: ResultsObserver<TaskItem, Never> @ObservationIgnored private var token: ObservationTracking.Token? var tasks: FetchResultsCollection<TaskItem> { observer.results } init(context: ModelContext) { let descriptor = FetchDescriptor<TaskItem>( sortBy: [SortDescriptor(\.name, order: .reverse)] ) observer = try! ResultsObserver(fetchDescriptor: descriptor, modelContext: context) } } struct RandomView: View { @State var viewModel: RandomViewModel? @Environment(\.modelContext) private var modelContext var body: some View { VStack { if let viewModel { List(viewModel.tasks) { foo in Text(foo.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(viewModel.observer.results.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } else { Text("Hello, World!") } } .task { if viewModel == nil { viewModel = RandomViewModel(context: modelContext) } } } } func testContainer() -> ModelContainer { let schema = Schema([ Item.self, TaskItem.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true) let container = try! ModelContainer(for: schema, configurations: [modelConfiguration]) let modelContext = container.mainContext for i in 1...20 { let item = TaskItem(name: "Sample Task \(i)", priority: Int.random(in: 1...5)) modelContext.insert(item) } return container } #Preview { NavigationStack { RandomView() } .modelContainer(testContainer()) } When I run the Preview or the simulator, the UI takes a while to actually load and show the results. If I try a version using @Query this doesn't happen import SwiftData import SwiftUI struct RandomQueryView: View { @Environment(\.modelContext) private var modelContext @Query(sort: [SortDescriptor(\TaskItem.name, order: .reverse)]) private var tasks: [TaskItem] var body: some View { List(tasks) { task in Text(task.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(tasks.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } } #Preview { NavigationStack { RandomQueryView() } .modelContainer(testContainer()) } Is this a bug in SwiftData ResultsObserver? or am I using it wrong? I add a recording of my simulator showing the difference
1
0
767
Jun ’26
SwiftData + CloudKit schema evolution post release
I have a SwiftData + CloudKit app that is deployed to the Mac App Store. As a diagram my situation looks like: On my Mac, I have installed the App Store version of the App. When developing it I run the app via Xcode, so I can have a debug build running. The initial stable schema was deployed to CloudKit production before the App release. Now, when I change the SwiftData schema again and run the Debug app on my Mac What happens is that: The SwiftData local store is on the latest schema The CloudKit schema for development is automatically updated That’s all good, but if I run the App Store app version of my app. By default, it uses the same SwiftData store for both builds of the app, which are being synced to different CloudKit schemas for development and production at the same time. As a result, I get an unreliable state where I have seen data duplication as a result, or CloudKit syncing just breaks. Also, since I’m developing the app, the changes to the schema in development may not make it to production, so I don’t want to promote those changes to production. So my question: What’s the recommended way to evolve the schema for an app already on the App Store? I haven’t seen any example or session from Apple that tackles this -what I consider common- use case. I tried to have different CloudKit containers for a "Dev" and "Prod" builds, but that wasn’t the solution.
0
0
810
Jun ’26
How to detect if a migration is required?
Hello, With Core Data, we can use the isConfiguration(withName:compatibleWithStoreMetadata:) method on an NSManagedObjectModel alongside metadata(for:) on NSPersistentStoreCoordinator to check if the on-disk store is up to date or not. Is this the way to do it too with SwiftData or do we have an easier way to check if the on-disk store will need to migrate? I want to inform my users in the UI when the app launches (or from widgets or app intents). Regards, Axel
0
0
800
Jun ’26
Better alternative to WWDC's `withContinuousObservation` in View initializers for SwiftData?
Hi everyone, I was watching the "Code-along: Add persistence with SwiftData" session and noticed a strange architectural choice at the end. They track model side-effects directly inside a SwiftUI View's initializer like this: init(activity: Activity, isLast: Bool, isEditing: Bool) { activity.token = withContinuousObservation(options: .didSet) { event in // ... side effects here } } This feels like a significant architectural smell. SwiftUI views are transient structures with no guaranteed lifetime—they can be initialized dozens of times a second during standard layout passes. Furthermore, if multiple views display or interact with the same Activity, this tracking work gets duplicated redundantly. I understand this is a workaround because attaching a standard didSet directly to a stored property inside a @Model class doesn't trigger cleanly due to how the macro expands back-end storage. To keep this data-logic in the model layer where it belongs, I came up with an alternative that maps a custom computed property over a real stored attribute using. Here is the pattern: import SwiftUI import SwiftData @Model class Item { // 1. Persist the actual database column under an internal property name private var _title: String // 2. Expose a public computed property to intercept mutations var title: String { get { _title } set { // Updating the backing variable automatically fires the macro's observation hooks _title = newValue updatedAt = .now // Our derived side-effect! } } var updatedAt: Date init(title: String) { self._title = title self.updatedAt = .now } } Why I prefer this over the WWDC approach: Separation of Concerns: The model handles its own data dependencies (updatedAt), meaning the View layer remains purely declarative. Predictable Execution: The mutation logic runs exactly once per write, regardless of how many views are rendering or re-initializing around the object. No Manual Observation Setup: Because _title is a real, macro-backed attribute, SwiftData’s generated access and withMutation hooks are invoked naturally when the computed property reads or writes to it. We don't have to manually manage tokens or observation blocks. What do you all think? Are there any hidden gotchas to manipulating the schema mapping via originalName like this, or is this a vastly superior layout to WWDC's view-bound observation snippet? The downside is now the SQLIte column is _TITLE instead of TITLE. Is there any workaround for that? There doesn't seem to be @Attribute(columnName: "title")
1
1
755
Jun ’26
Handling SwiftData Initialization Errors
The traditional way to initialize a SwiftData app looks like some variation of the following: @main struct TrainingCornerApp: App { let dbSchema: Schema = ... init() { } var body: some Scene { WindowGroup { MainAppScreen() .modelContainer(modelContainer) } } } private var modelContainer: ModelContainer { let container: ModelContainer let modelConfiguration = ModelConfiguration(schema: dbSchema, isStoredInMemoryOnly: false, cloudKitDatabase: .automatic) do { container = try ModelContainer(for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) } catch { fatalError("Failed to create model container: \(error.localizedDescription)") } return container } } That is, if creating the modelContainer fails, the app aborts with a fatalError. What I want to do is have the application present an alert message for the user before terminating. (Let the user know the app can't run and suggest how to get help -- that sort of thing.) However, I've been having a hard time getting this to work, and it seems that the problems are related to trying to generate the alert at such an early stage in app startup. Does anyone have ideas/suggestions on how I might do this?
Replies
0
Boosts
0
Views
87
Activity
4d
SwiftData public sharing
I have an Apple app that uses SwiftData and icloud to sync the App's data across users' devices. Everything is working well. However, I am facing the following issue: SwiftData does not support public sharing of the object graph with other users via iCloud. How can I overcome this limitation without stopping using SwiftData? Thanks in advance!
Replies
3
Boosts
7
Views
875
Activity
4d
Best practices
Hi everyone, I'm Alexsander. My friends call me Lexie. I have been working as software developer since 6 years ago, I have a lot of experience with Java and I started working with Angular since the last year. I am new in the Apple ecosystem and I have a question about best practices in full native Swift apps. There is any source (blogs, youtube channels, books, et al.) where I can understand the best practices? Like, I've heard about MVVM to scalable apps but I don't know exactly how to apply it. I think it's because usually I do not have my front-end components in the same project of my backend. I've been watching some videos from Apple Developer youtube channel and they are absolutely amazing, but they only keep teaching people to use the "raw" resources, not matching with the best practices. For example, I saw using swift data we do not need to write any SQL Query, unlike Java Ecossystem where even we use a ORM we usually write our queries natively, whether creating a table or fetching data.
Replies
2
Boosts
0
Views
572
Activity
6d
How to respond to alarms that appear when I compile my app
When compiling the app on an iPhone running iOS 16, the following alerts appear. What steps should I take to resolve this? UIScene lifecycle will soon be required. Failure to adopt will result in an assert in the future. CoreUI: CUIThemeStore: No theme registered with id=0
Replies
0
Boosts
0
Views
212
Activity
1w
Loading an array
How can I pre-load an array that I created using Swiftdata? I am creating a deck of cards and I want the user to be able to add/delete from the deck.
Replies
1
Boosts
0
Views
203
Activity
1w
SwiftData query returns "private" string in WidgetExtension
Hello, I am trying to set up Widgets in my app. I want to fetch my data in the SwiftData container that is shared between my app and my WidgetExtension with App Group. let modelContext = ModelContext(modelContainer) let predicate = #Predicate<Test>{ return $0.attribute == true } return try modelContext.fetch(FetchDescriptor (predicate: predicate, sortBy: [SortDescriptor(\Test.name)])) When this code is run in my WidgetExtension, returned objects attributes values are replaced with "" string. In the logs, Swift Data writes Query returned unrequested identifiers that have been dropped: <private> Any idea what I might be doing wrong to share my SwiftData between my App and my Widget? App Groups capability has been added to both apps and extension with the same identifier. Thank you
Replies
2
Boosts
0
Views
415
Activity
3w
SwiftData Decimal loses precision after save/fetch with a minimal reproduction
I believe I may have found a SwiftData persistence bug, but I'd like to verify that I'm not overlooking a documented limitation before filing Feedback. This minimal example appears to lose precision when persisting a Decimal: import Foundation import SwiftData @Model class Item { var value: Decimal init(_ value: Decimal) { self.value = value } } let original = Decimal(string: "123456789012345.6")! let container = try ModelContainer( for: Item.self, configurations: .init(isStoredInMemoryOnly: true) ) let context = ModelContext(container) context.insert(Item(original)) try context.save() let fetched = try ModelContext(container) .fetch(FetchDescriptor<Item>()) .first! print(original) print(fetched.value) Output: 123456789012345.6 123456789012346 A few observations from additional testing: Decimal(string:) preserves the value before persistence. Decimal ↔ NSDecimalNumber bridging preserves the value in separate tests. The value remains exact after model initialization, insertion, and save() on the registered object. The first Swift-visible precision loss appears after fetching from a new ModelContext. As a control, I repeated the test using Core Data with an NSInMemoryStoreType store and an NSDecimalAttributeType attribute. That round-tripped the tested values exactly. Inspecting the SQLite store generated by SwiftData showed the affected value stored as a REAL. At this point it appears the precision loss occurs somewhere in the SwiftData/Core Data persistence pipeline rather than in Decimal itself. Can anyone reproduce this, or is there a documented limitation on Decimal persistence in SwiftData that I have missed? If this is expected behavior, what is the recommended way to persist exact decimal values for financial applications?
Replies
0
Boosts
0
Views
362
Activity
3w
SwiftData Decimal loses precision after save/fetch with a minimal reproduction
I believe I may have found a SwiftData persistence bug, but I'd like to verify that I'm not overlooking a documented limitation before filing Feedback. This minimal example appears to lose precision when persisting a Decimal: import Foundation import SwiftData @Model class Item { var value: Decimal init(_ value: Decimal) { self.value = value } } let original = Decimal(string: "123456789012345.6")! let container = try ModelContainer( for: Item.self, configurations: .init(isStoredInMemoryOnly: true) ) let context = ModelContext(container) context.insert(Item(original)) try context.save() let fetched = try ModelContext(container) .fetch(FetchDescriptor<Item>()) .first! print(original) print(fetched.value) Output: 123456789012345.6 123456789012346 A few observations from additional testing: Decimal(string:) preserves the value before persistence. Decimal ↔ NSDecimalNumber bridging preserves the value in separate tests. The value remains exact after model initialization, insertion, and save() on the registered object. The first Swift-visible precision loss appears after fetching from a new ModelContext. As a control, I repeated the test using Core Data with an NSInMemoryStoreType store and an NSDecimalAttributeType attribute. That round-tripped the tested values exactly. Inspecting the SQLite store generated by SwiftData showed the affected value stored as a REAL. At this point it appears the precision loss occurs somewhere in the SwiftData/Core Data persistence pipeline rather than in Decimal itself. Can anyone reproduce this, or is there a documented limitation on Decimal persistence in SwiftData that I have missed? If this is expected behavior, what is the recommended way to persist exact decimal values for financial applications?
Replies
0
Boosts
0
Views
353
Activity
3w
SwiftData Model didset
Hi, I'm trying out new SwiftData in a small Xcode project. It seems that the property observers didSet and willSet don't work anymore for swift data anymore. In code like this, the didSet does nothing and seems to never be called. @Model public final class importConfig: Identifiable, ObservableObject{ @Attribute(.unique) public var id: UUID /// Name of the configuration var configName: String /// Numbers App document to open var numbersFilePath: URL? /// Indicate wether current <numbersFilePath> Numbers App document has been loaded and analyzed var isLoaded: Bool = false /// Current selected sheet var selectedSheetID: UUID? { didSet { selectedSheetID = nil print("test") } } } Am I doing something wrong or is it the expected behavior ? If it is the expected behavior, how can I add "business" rules when setting/unsetting value to model properties ? I tried to add rules directly with .onchange() in my views, but this way I have to repeat the same rules/code. Is there any alternative to do so ? Thank you
Replies
3
Boosts
1
Views
2.1k
Activity
Jul ’26
Nedd help
Hy my name is max i would need help lurning i‘m trying to get developer mods to make apps
Replies
0
Boosts
0
Views
612
Activity
Jun ’26
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
4
Boosts
0
Views
1.5k
Activity
Jun ’26
Prevent SwiftData Upserts
Following the premise that database integrity should be handled by rules in the schema as much as possible, the automatic UPSERT whereby trying to create a record with the same unique key as a record that already exists does not trigger an INSERT error but automatically updates the existing record is pretty alien. I really don't want to enforce this on business logic and I want the backend to do the work. Is there away to prevent the UPSERT?
Replies
0
Boosts
0
Views
650
Activity
Jun ’26
Under what circumstances does @Query call body?
Hi I was wondering under what circumstances does @Query call body. Does it call it when the result set changes? E.g. object added/removed/moved. Does it also call when the result set is the same but a property of a model changed? I'd prefer 1, since models are @Observable my Views can handle tracking if they need to update when a property of a model changes. But I am concerned it is 2 which would cause unnecessary calls to body? E.g. a ForEach would needlessly be reinit since the model array is exactly the same. So which is it? By the way it would be useful if the docs could be updated with this important info. Thanks
Replies
1
Boosts
0
Views
704
Activity
Jun ’26
SwiftData, CloudKit and 2 AppleIDs
I have a SwiftData app that runs on iOS, iPadOS, and MacCatalyst and which uses CloudKit for inter-device sync. Unfortunately, I also have two AppleIDs (which I 'll refer to as OLDID and NEWID). Although all three devices (phone, pad and desktop) are currently set up with NEWID as the active AppleID, during development and testing, my desktop Mac used OLDID. Apparently, the system remembers the AppleID to use with each CloudKit app (based on the AppleID active at time of first use), because the desktop app and the mobile apps apparently sync to different AppleID accounts. I can delete the local database on the desktop and delete the local app on the mobile devices and in each case, reloading/rerunning the app causes the respective databases to be restored from the cloud. The two mobile devices sync with each other, but not with the desktop; the desktop doesn't sync with either device. And the two databases have decidedly different contents. My goal is to consolidate everything so that there is one database, shared and synced between desktop, pad, phone and cloud. I presume that there is a setting somewhere (but clearly NOT in the app's sandboxed container) that specifies what iCloud account to use for that (and each) app. Note: I have other apps which sync between all my devices, so the setting must be on a per-app basis. I also presume that if I changed it's value on my desktop (so that all three devices used the same AppleID for cloud services for my app), that the content of the local database on my desktop would be synced automatically to the NEWID cloud account and then (also automatically) synchronized with my mobile devices. I.e., I speculate that I can solve all my problems by changing that setting on my desktop Mac. So I have two questions: Is all this correct? How do I make this setting change. (I.e., where is it and how do I change it) Does anyone have any experience and can help with this issue? Thanks
Replies
3
Boosts
0
Views
827
Activity
Jun ’26
SwiftData predicate filtered by enum case
I have several Swift Data types with a property of type enum. Whenever I've tried to write a predicate returning data objects only of a certain enum case, the compiler throws an error from the macro at build time. (which I don't have handy, sorry...). Is this supported? And if so, how would you write the predicate? @Model public final class AlbumList { // ... public var listType: AlbumListType // ... } public enum AlbumListType: String, CaseIterable, Codable { case listener case dj }
Replies
5
Boosts
2
Views
924
Activity
Jun ’26
Delay when using ResultsObserver over @Query?
I was testing how to use ResultsObserver on a ViewModel in SwiftData. In Xcode 27, Developer v1, I have the following view import SwiftUI import SwiftData @Model class TaskItem { var name: String var priority: Int init(name: String, priority: Int) { self.name = name self.priority = priority } } @Observable @MainActor class RandomViewModel { let observer: ResultsObserver<TaskItem, Never> @ObservationIgnored private var token: ObservationTracking.Token? var tasks: FetchResultsCollection<TaskItem> { observer.results } init(context: ModelContext) { let descriptor = FetchDescriptor<TaskItem>( sortBy: [SortDescriptor(\.name, order: .reverse)] ) observer = try! ResultsObserver(fetchDescriptor: descriptor, modelContext: context) } } struct RandomView: View { @State var viewModel: RandomViewModel? @Environment(\.modelContext) private var modelContext var body: some View { VStack { if let viewModel { List(viewModel.tasks) { foo in Text(foo.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(viewModel.observer.results.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } else { Text("Hello, World!") } } .task { if viewModel == nil { viewModel = RandomViewModel(context: modelContext) } } } } func testContainer() -> ModelContainer { let schema = Schema([ Item.self, TaskItem.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true) let container = try! ModelContainer(for: schema, configurations: [modelConfiguration]) let modelContext = container.mainContext for i in 1...20 { let item = TaskItem(name: "Sample Task \(i)", priority: Int.random(in: 1...5)) modelContext.insert(item) } return container } #Preview { NavigationStack { RandomView() } .modelContainer(testContainer()) } When I run the Preview or the simulator, the UI takes a while to actually load and show the results. If I try a version using @Query this doesn't happen import SwiftData import SwiftUI struct RandomQueryView: View { @Environment(\.modelContext) private var modelContext @Query(sort: [SortDescriptor(\TaskItem.name, order: .reverse)]) private var tasks: [TaskItem] var body: some View { List(tasks) { task in Text(task.name) } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add Task") { let task = TaskItem(name: "ZZ New Task \(tasks.count + 1)", priority: 2) print("add \(task.name)") modelContext.insert(task) } } } } } #Preview { NavigationStack { RandomQueryView() } .modelContainer(testContainer()) } Is this a bug in SwiftData ResultsObserver? or am I using it wrong? I add a recording of my simulator showing the difference
Replies
1
Boosts
0
Views
767
Activity
Jun ’26
CloudKit Swiftdata Support for Public Databases
There’s hundreds of forms of people wanting and waiting for swifitdata support for CloudKit public or shared databases. Is this ever going to come or should I just give up and use my own database dont really want to learn core data for such a small part of my app
Replies
0
Boosts
1
Views
747
Activity
Jun ’26
SwiftData + CloudKit schema evolution post release
I have a SwiftData + CloudKit app that is deployed to the Mac App Store. As a diagram my situation looks like: On my Mac, I have installed the App Store version of the App. When developing it I run the app via Xcode, so I can have a debug build running. The initial stable schema was deployed to CloudKit production before the App release. Now, when I change the SwiftData schema again and run the Debug app on my Mac What happens is that: The SwiftData local store is on the latest schema The CloudKit schema for development is automatically updated That’s all good, but if I run the App Store app version of my app. By default, it uses the same SwiftData store for both builds of the app, which are being synced to different CloudKit schemas for development and production at the same time. As a result, I get an unreliable state where I have seen data duplication as a result, or CloudKit syncing just breaks. Also, since I’m developing the app, the changes to the schema in development may not make it to production, so I don’t want to promote those changes to production. So my question: What’s the recommended way to evolve the schema for an app already on the App Store? I haven’t seen any example or session from Apple that tackles this -what I consider common- use case. I tried to have different CloudKit containers for a "Dev" and "Prod" builds, but that wasn’t the solution.
Replies
0
Boosts
0
Views
810
Activity
Jun ’26
How to detect if a migration is required?
Hello, With Core Data, we can use the isConfiguration(withName:compatibleWithStoreMetadata:) method on an NSManagedObjectModel alongside metadata(for:) on NSPersistentStoreCoordinator to check if the on-disk store is up to date or not. Is this the way to do it too with SwiftData or do we have an easier way to check if the on-disk store will need to migrate? I want to inform my users in the UI when the app launches (or from widgets or app intents). Regards, Axel
Replies
0
Boosts
0
Views
800
Activity
Jun ’26
Better alternative to WWDC's `withContinuousObservation` in View initializers for SwiftData?
Hi everyone, I was watching the "Code-along: Add persistence with SwiftData" session and noticed a strange architectural choice at the end. They track model side-effects directly inside a SwiftUI View's initializer like this: init(activity: Activity, isLast: Bool, isEditing: Bool) { activity.token = withContinuousObservation(options: .didSet) { event in // ... side effects here } } This feels like a significant architectural smell. SwiftUI views are transient structures with no guaranteed lifetime—they can be initialized dozens of times a second during standard layout passes. Furthermore, if multiple views display or interact with the same Activity, this tracking work gets duplicated redundantly. I understand this is a workaround because attaching a standard didSet directly to a stored property inside a @Model class doesn't trigger cleanly due to how the macro expands back-end storage. To keep this data-logic in the model layer where it belongs, I came up with an alternative that maps a custom computed property over a real stored attribute using. Here is the pattern: import SwiftUI import SwiftData @Model class Item { // 1. Persist the actual database column under an internal property name private var _title: String // 2. Expose a public computed property to intercept mutations var title: String { get { _title } set { // Updating the backing variable automatically fires the macro's observation hooks _title = newValue updatedAt = .now // Our derived side-effect! } } var updatedAt: Date init(title: String) { self._title = title self.updatedAt = .now } } Why I prefer this over the WWDC approach: Separation of Concerns: The model handles its own data dependencies (updatedAt), meaning the View layer remains purely declarative. Predictable Execution: The mutation logic runs exactly once per write, regardless of how many views are rendering or re-initializing around the object. No Manual Observation Setup: Because _title is a real, macro-backed attribute, SwiftData’s generated access and withMutation hooks are invoked naturally when the computed property reads or writes to it. We don't have to manually manage tokens or observation blocks. What do you all think? Are there any hidden gotchas to manipulating the schema mapping via originalName like this, or is this a vastly superior layout to WWDC's view-bound observation snippet? The downside is now the SQLIte column is _TITLE instead of TITLE. Is there any workaround for that? There doesn't seem to be @Attribute(columnName: "title")
Replies
1
Boosts
1
Views
755
Activity
Jun ’26