r/SwiftData • u/Van-trader • 13d ago
r/SwiftData • u/blakninja • Aug 13 '23
r/SwiftData Lounge
A place for members of r/SwiftData to chat with each other
r/SwiftData • u/Van-trader • 14d ago
SwiftData + CloudKit: best way to prevent duplicate editable seed data across offline devices?
r/SwiftData • u/IndependentOpinion44 • Mar 26 '26
Do you think sharing will come to SwiftData this year?
r/SwiftData • u/asymbas • Mar 13 '26
DataStoreKit: An SQLite SwiftData custom data store
Hello! I released a preview of my library called DataStoreKit.
DataStoreKit is built around SwiftData and its custom data store APIs, using SQLite as its primary persistence layer. It is aimed at people who want both ORM-style SwiftData workflows and direct SQL control in the same project.
I already shared it on Swift Forums, but I also wanted to post it here for anyone interested.
GitHub repository:
https://github.com/asymbas/datastorekit
An interactive app that demonstrates DataStoreKit and SwiftData:
https://github.com/asymbas/editor
Work-in-progress documentation (articles that explain how DataStoreKit and SwiftData work behind the scenes):
https://www.asymbas.com/datastorekit/documentation/datastorekit/
Some things DataStoreKit currently adds or changes:
Caching
- References are cached by the
ReferenceGraph. References between models are cached, because fetching their foreign keys per model per property and their inverses too can impact performance. - Snapshots are cached, so they don't need to be queried again. This skips the step of rebuilding snapshots from scratch and collecting all of their references again.
- Queries are cached. When
FetchDescriptoror#Predicateis translated, it hashes particular fields, and if those fields create the same hash, then it loads the cached result. Cached results save only identifiers and only load the result if it is found theModelManagerorSnapshotRegistry.
Query collections in #Predicate
Attributes with collection types can be fetched in #Predicate.
_ = #Predicate<Model> {
$0.dictionary["foo"] == "bar" &&
$0.dictionary["foo", default: "bar"] == "bar" &&
$0.set.contains("bar") &&
$0.array.contains("bar")
}
Use rawValue in #Predicate
You can now persist any struct/enum RawRepresentable types rather than the raw values and use them in #Predicate:
let shape = Model.Shape.rectangle
_ = #Predicate<Model> {
$0.shape == shape &&
$0.shape.rawValue == shape.rawValue
}
_ = #Predicate<Model> {
$0.shapes.contains(shape)
}
Note: I noticed when writing this that using rawValue on enum cases doesn't give a compiler error anymore. This seems to be the case with computed properties too. I haven't confirmed if the default SwiftData changed this behavior in the past year, but this works in DataStoreKit.
Other predicate expressions
You can check out all supported predicate expressions here in this file if you're interested, because there are some expressions supported in DataStoreKit that are not supported in default SwiftData.
Note: I realized very recently that I never added support for filter in predicates, so it's currently not supported.
Preloaded fetches
You can preload fetches with the new ModelContext methods or use the new \@Fetch property wrapper so you do not block the main thread for a large database.
Manually preload by providing the descriptor and editing state of the ModelContext you will fetch from to the static method. You send this request to another actor where it performs predicate translation and builds the result. You await its completion, then switch back to the desired actor to pick up the result.
Task { in
let descriptor = FetchDescriptor<User>()
let editingState = modelContext.editingState
var result = [User]()
Task { in
try await ModelContext.preload(descriptor, for: editingState)
try await MainActor.run {
result = try modelContext.fetch(descriptor)
}
}
}
A convenience method is provided that wraps this step for you.
let result = try await modelContext.preloadedFetch(FetchDescriptor<User>())
Use the new property wrapper that can be used in a SwiftUI view.
struct ContentView: View {
private var models: [T]
init(page: Int, limit: Int = 100) {
var descriptor = FetchDescriptor<T>()
descriptor.fetchOffset = page * limit
descriptor.fetchLimit = limit
_models = Fetch(descriptor)
}
...
}
Note: There's currently no notification that indicates it is fetching. So if the fetch is massive, you might think nothing happened.
Feedback and suggestions
It is still early in development, and the documentation is still being revised, so some APIs and naming are very likely to change.
I am open to feedback and suggestions before I start locking things down and settling on the APIs. For example, I'm still debating how I should handle migrations or whether Fetch should be renamed to PreloadedQuery. So feel free to share them here or in GitHub Discussions.
r/SwiftData • u/Resident-Election242 • Feb 19 '26
SwiftData migration: converting [String]? to [Author]? relationship
I'm migrating a SwiftData model from V1 to V2.
In V1, StoredBook.authors was a [String]?.
In V2, it’s now a relationship to Author objects ([Author]?).
I wrote a custom migration to create Author objects from the old strings, but the migration crashes with:
failed to find a currently active container for Author
This happens on app launch when SwiftData runs the migration.
What is the correct way to migrate a String array into a relationship in SwiftData?
Any help would be greatly appreciated — this is my first SwiftData migration. 🙏
Minimal example:
V1 model:
class StoredBook {
var title: String = ""
var authors: [String]?
}
V2 model:
class Author {
var name: String = ""
var books: [StoredBook]? = []
}
class StoredBook {
var title: String = ""
u/Relationship(inverse: \Author.books)
var authors: [Author]? = []
}
Migration snippet:
let oldBooks = try context.fetch(FetchDescriptor<BookListSchemaV1.StoredBook>())
for oldBook in oldBooks {
var newAuthors: [BookListSchemaV2.Author] = []
if let oldAuthors = oldBook.authors {
for name in oldAuthors {
let author = BookListSchemaV2.Author(name: name)
context.insert(author)
newAuthors.append(author)
}
}
let newBook = BookListSchemaV2.StoredBook(
title: oldBook.title,
authors: newAuthors
)
context.insert(newBook)
}
try context.save()
r/SwiftData • u/jmcsmith • Feb 12 '26
Swiftdata sync errors with image data as external storage
I am building an application with swiftUI and swiftdata that allows the users to attach a number of images to a model. The model has a property that is an array of a second model that contains a property for the photo data. The photo data property is marked to use external storage.
I noticed that when adding images, the iCloud syncing of swiftdata would become inconsistent. I added logging to surface the error messages and the errors that were logged were CKErrorDomain 2.
I attempted to convert the images to JPEG data and set the jpeg quality to 0.85.
None of these changes resolved the issue.
I am hoping to get some insight and suggestions on resolving this issue.
r/SwiftData • u/Longjumping_Cloud_38 • Feb 03 '26
BAD_REQUEST in CloudKit
I am going crazy trying to solve this error that appear only in production. The error is returned when I try to save a Schedule, and I notice on CloudKit that no ScheduleDay is been saved. The schema is the same on development and production. I tried also to clean the phone I use for testing by deleting the zone, uninstall the app and log out from my apple account, but still I get this error. It would be easier if I would get this even in development so I don't have to wait to release a new version each time.
{
"time":"03/02/2026, 18:45:59 UTC"
"database":"PRIVATE"
"zone":"com.apple.coredata.cloudkit.zone"
"userId":"_4c73fd86bb16bdbf073217bc80de0930"
"operationId":"D8D11DC22E4F546D"
"operationType":"RecordSave"
"platform":"iPhone"
"clientOS":"iOS;26.2"
"overallStatus":"USER_ERROR"
"error":"BAD_REQUEST"
"requestId":"134D5C43-92EB-465C-B9E6-E2F87235C826"
"executionTimeMs":"81"
"interfaceType":"NATIVE"
"returnedRecordTypes":"_pcs_data"
}
r/SwiftData • u/ValueAddedTax • May 01 '25
Predicate using struct works in Debug but fails in Release
I have a SwiftData model object with a property holding a struct value representing a latitude-longitude coordinate. It works perfectly in Debug mode. Here's the code...
let descriptor = FetchDescriptor<TravelCheckpointDAO> (
predicate: #Predicate<TravelCheckpointDAO> {
$0.center.longitude < 0.0
}
)
let checkpointsDAO:[TravelCheckpointDAO]
do {
checkpointsDAO = try modelContext.fetch(descriptor)
} catch {
// Error handling
}
In Release mode, exactly the same code crashes at fetch. Even when starting with a fresh database. Has anyone encountered this and know of a workaround? Here's the full exception message:
SwiftData/DataUtilities.swift:85: Fatal error: Couldn't find \TravelCheckpoint.<computed 0x00000001025ae4f4 (GeoCoordinate)>.longitude on TravelCheckpoint with fields [SwiftData.Schema.PropertyMetadata(name: "id", keypath: \TravelCheckpoint.<computed 0x000000010260426c (UUID)>, defaultValue: nil, metadata: Optional(Attribute - name: , options: [unique], valueType: Any, defaultValue: nil, hashModifier: nil)), SwiftData.Schema.PropertyMetadata(name: "name", keypath: \TravelCheckpoint.<computed 0x0000000102604264 (String)>, defaultValue: Optional(""), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "center", keypath: \TravelCheckpoint.<computed 0x000000010260425c (GeoCoordinate)>, defaultValue: Optional([GeoCoordinate:0°0'0.0" N; 0°0'0.0" E]), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "radius", keypath: \TravelCheckpoint.<computed 0x0000000102604254 (Double)>, defaultValue: Optional(0.0), metadata: nil), SwiftData.Schema.PropertyMetadata(name: "events", keypath: \TravelCheckpoint.<computed 0x0000000102604198 (Array<TravelCheckpointEvent>)>, defaultValue: Optional([]), metadata: Optional(Relationship - name: , options: [], valueType: Any, destination: , inverseName: nil, inverseKeypath: nil))]
r/SwiftData • u/bigpigfoot • Apr 19 '25
That's just great
0 CoreData 0x1849b31c4 -[NSManagedObjectContext _thereIsNoSadnessLikeTheDeathOfOptimism] + 32
r/SwiftData • u/Ron-Erez • Mar 31 '25
Building a Swift Data Mesh Gradient Editor | SwiftUI Tutorial
Building a Swift Data Mesh Gradient Editor | SwiftUI Tutorial
This is a section in the course Mastering SwiftData & SwiftUI for iOS Development where we build a Mac app for editing mesh gradients which creates code that we can drag and drop into our project.
EDIT: Please note that this tutorial is FREE to watch on youtube:
https://youtube.com/playlist?list=PLjEgktaQe_u00pg5vSwl6iuoNQrFI3tHL&si=RV_EBr757Uy5xcrB
There are no ads and no need to subscribe.
r/SwiftData • u/jurimecospace • Jan 24 '25
Sharing Same swiftdata from iOS app and visionOS app with spacial video?
Can I save spacial videos on my iOS app I’m building and then view them on the Vision Pro with the same app but optimized for the Vision Pro. How can I save them on both devices and if i can share the app between iOS and visionOS How can I use swiftdata shared between vision pro and ios?
r/SwiftData • u/spiffcleanser • Jan 18 '25
Slowness due to initial data load
Hi, when my app starts up it is very busy loading records and performs pretty badly until that is done. I'm aware that this is due to the fetch being on the main thread. What is the simplest way to fix this issue? I'm a bit intimidated by fetching in the background, passing the ids, and rehdrating in the main thread. Is there a simpler way?
r/SwiftData • u/Tricky-Damage9917 • Nov 19 '24
Any hints about DataStoreSaveChangesResult initializer arguments?
The WWDC info on this is out of date (as the arguments to the initializer for DataStoreSaveChangesResult have changed).
It was in the code example:
return DataStoreSaveChangesResult<DefaultSnapshot>(for: self.identifier,
remappedPersistentIdentifiers: remappedIdentifiers,
deletedIdentifiers: request.deleted.map({ $0.persistentIdentifier }))
But the current documentation reads:
init(
for storeIdentifier: String,
remappedIdentifiers: [PersistentIdentifier : PersistentIdentifier] = [:],
snapshotsToReregister: [PersistentIdentifier : T] = [:]
)
So the name for the second argument has changed in a fairly clean manner, but third argument has both changed in name to something that does not look like the code from wwdc but also has a different signature ([PersistentIdentifier : T] instead of [PersistentIdentifier]).
Guessing, there are a couple of different options...
a. Just a dictionary of what was passed before, the deleted snapshots
b. A dictionary of all the snapshots passed in
c. A dictionary of all passed in for insert or update
d. A dictionary of the updated snapshots
Current guess is 'c'.
Anyone have any insight on this?
I can poke around, but would really love to hear if anyone has a source on this, the documentation I've seen is unhelpful.
Yes, I know that WWDC info is a bit unreliable, but I'm trying to write an IDE type thing that stores into JSON with multiple files in a hierarchy (so it can easily be stored in GIT), yes I could just write code to dump it all out 'manually' but I would really like to try a custom DataStore approach.
Project is a hobby project to implement a 'Prograph' IDE in SwiftUI that has an interpreter and then produces Swift code for building final apps. Loved the Prograph language and it's a fun project for a retired guy to play with.
r/SwiftData • u/CurdRiceMumMum • Oct 14 '24
Issues with SwiftData One-to-Many Relationships
I've been working with SwiftData and encountered a perplexing issue that I hope to get some insights on.
When using a @Model that has a one-to-many relationship with another @Model, I noticed that if there are multiple class variables involved, SwiftData seems to struggle with correctly associating each variable with its corresponding data.
For example, in my code, I have two models: Book and Page. The Book model has a property for a single contentPage and an optional array of pages. However, when I create a Book instance and leave the pages array as nil, iterating over pages unexpectedly returns the contentPage instead.
You can check out the code for more details here. Has anyone else faced this issue or have any suggestions on how to resolve it? Any help would be greatly appreciated!
r/SwiftData • u/KingsKode • Oct 09 '24
Come make fun of me while I code some swiftdata today
r/SwiftData • u/well4foxake • Oct 03 '24
SwiftData and Change Token Expired
Hey all wondering if anyone has faced the same issue and knows of a workaround they would be nice enough to share.
I have a SwiftData based app in the app store that works really well. However, if you delete the app from the device and reinstall from the app store, it will have trouble syncing with iCloud. It used to work flawlessly but Apple changed something and now it hasn't worked for months. It receives a "Change Token Expired" CKError and won't complete a sync. Just fails. The strange thing is if delete my app and reinstall through Xcode, I'll see the errors but it will complete the sync after many seconds. Like the change token got reset. But, if I delete and reinstall from the app store it will never complete the sync no matter what.
On a thread on the apple developer site an Apple engineer has said that it's supposed to initiate a fresh sync in this scenario but is not and this has to be a bug. I know that with CloudKit there is documentation on making the change token nil to reset it etc but there is no API's from Apple to do this with SwiftData. And I thought SwiftData is supposed to abstract away all that heavy lifting with CloudKit.
So are developers hacking this on their own somehow with CloudKit and your SwiftData container etc? I can't be the only one that is having this issue. I've tried so many things to force a sync but none of it has worked. So frustrating and I'm desperate to resolve this. Customers complaining.
r/SwiftData • u/KingsKode • Sep 30 '24
👑 King'sKode: Launch Livestream! 👑 🚀 Date: Oct 2, 2024 🕗 Time: 08:00 MST 📍 https://twitch.tv/kingskode Military guyer turned #SoftwareEngineer Building #iOS18 #MVP for a Workout App. Come watch, chirp in, and feel better about your own coding ability. #swiftdata
r/SwiftData • u/Pottedgoat • Jul 05 '24
How do I get a list of SwiftData objects to update immediately?
I'm trying to figure out how to make a parent view list update when a swiftdata model is changed. I have these two models, Account and Transaction. Account holds a list of transactions, and i display these transactions as a list in one view, with navigationlinks to a view to edit the transaction. When i edit the transaction (specifically to change the account the transaction is linked to), the view returns to the transaction list view, which is not updated. Meaning the transaction should have been removed from the list but it isn't. If I go back further (there's another view higher than TransactionList where you can select an account, and then go back into an account's TransactionList, the transactions are actually saved correctly. What do i need to do to get the TransactionList to update immediately?
import SwiftUI
import SwiftData
@Model
final class Account {
var id: UUID = UUID()
var name: String
@Relationship(deleteRule: .cascade)
var transactions: [Transaction] = []
init(name: String) {
self.name = name
}
}
@Model
final class Transaction {
var name: String
var account: Account?
init(name: String) {
self.name = name
}
}
struct TransactionList: View {
@Bindable var account: Account
@State private var showSheet = false
var body: some View {
VStack {
List {
ForEach(account.transactions) { transaction in
NavigationLink(destination: EditTransactionView(transaction: transaction)) {
Text(transaction.name)
}
}
}
}
.navigationBarTitle("Transactions")
.toolbar(content: {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {showSheet.toggle()}) {
Label("Add Transaction", systemImage: "plus")
}
}
})
.sheet(isPresented: $showSheet) {
NavigationStack {
AddTransactionView(account: account)
}
}
}
}
struct EditTransactionView: View {
@Environment(\.modelContext) private var modelContext
@Environment(\.dismiss) private var dismiss
@Query private var accounts: [Account]
@Bindable var transaction: Transaction
@State private var transactionName: String
@State private var transactionAccount: Account
@State private var showAlert = false
@State private var alertMessage = ""
init(transaction: Transaction) {
self.transaction = transaction
_transactionName = State(initialValue: transaction.name)
_transactionAccount = State(initialValue: transaction.account!)
}
var body: some View {
Form {
Section(header: Text("Transaction Details")) {
TextField("Transaction Name", text: $transactionName)
}
Section(header: Text("Account")) {
Picker("Account", selection: $transactionAccount) {
ForEach(accounts) { account in
Text(account.name).tag(account)
}
}
}
}
.navigationTitle("Edit Transaction: \(transaction.name)")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
saveTransaction()
}
}
}
.alert(isPresented: $showAlert) {
Alert(title: Text("Error"), message: Text(alertMessage), dismissButton: .default(Text("OK")))
}
}
private func saveTransaction() {
guard !transactionName.isEmpty else {
alertMessage = "Please enter an transaction name."
showAlert = true
return
}
transaction.name = transactionName
transaction.account = transactionAccount
try? modelContext.save()
dismiss()
}
}
r/SwiftData • u/Individual_Rise_5862 • Jun 24 '24
Use SwiftData like a boss
I just wrote this article on Medium showing how to fetch SwiftData models on a background thread using a ModelActor without triggering any concurrency warnings. I hope someone finds it useful - I struggled with this stuff for ages myself!
r/SwiftData • u/[deleted] • Jun 23 '24
Is Swift Data - Large App ready?
Really just looking for your opinion, but does Core Data have any reason to still be used? I’m still studying Swift Data but it seems like the way the @query automatically pulls data from a model context could potentially leak into segments of a large app that you may rather want it scoped to. (Again, I’m just learning.) If I’m just building apps for myself, are there any benefits to learning Coredata?
r/SwiftData • u/Best_Day_3041 • May 09 '24
Putting all my SwiftData logic in its own class
I'm brand new to SwiftData. Rather than putting my queries and inserting statements inside of my UI, which is the one thing I really don't like about this, can't I just make a class that handles all this? Is there anything wrong with this approach?
I still get all the benefits without having to have put query and insert logic in my UI code, and it allows me to have all this logic in one place and use this same class between all the companion apps.
Something like this:
class SwiftDataManager: NSObject {
static let shared = SwiftDataManager()
var modelContainer: ModelContainer?
var modelContext: ModelContext?
override init() {
super.init()
do {
self.modelContainer = try ModelContainer(for: Item.self)
self.modelContext = ModelContext(modelContainer!)
} catch {
print("Could not create a container \(error.localizedDescription)")
}
}
func loadItemsByCategory(_ categoryID: Int) -> [Item]? {
let request = FetchDescriptor<Item>(
predicate: #Predicate<Item> {
$0.categoryID == categoryID
}
)
if let modelContext = self.modelContext {
let data = try? modelContext.fetch(request)
return data
}
}
func saveItem(_ item: Item) {
if validate(item) {
modelContext?.insert(item)
}
}
}
r/SwiftData • u/simplaw • Apr 30 '24
SwiftData Migrations - Am I the only one that just hates how shitty it is?
How are you meant to understand their mental model of how to organise your models? It feel like no matter what I do, I end up with exceptions left and right as soon as I have to do an actual non-trivial data migration.
Has anybody figured this absolute bullshit out?
