swiftdata

Implement, review, or improve data persistence using SwiftData. Use when defining @Model classes with @Attribute, @Relationship, @Transient, #Unique, or #Index; when querying with @Query, #Predicate, FetchDescriptor, or SortDescriptor; when configuring ModelContainer and ModelContext for SwiftUI or

By dpearson2699 · 3,594 installs

npx skills add dpearson2699/swift-ios-skills --skill swiftdata

Source repository · Upstream listing

SwiftData Persist, query, and manage structured data in iOS 26+ apps using SwiftData with Swift 6.3. Contents [Model Definition]( model definition) [ModelContainer Setup]( modelcontainer setup) [CloudKit Sync]( cloudkit sync) [CRUD Operations]( crud operations) [ @Query in SwiftUI ]( query in swiftui) [ Predicate]( predicate) [FetchDescriptor]( fetchdescriptor) [Schema Versioning and Migration]( schema versioning and migration) [Core Data Coexistence Boundary]( core data coexistence boundary) [Concurrency ( @ModelActor )]( concurrency modelactor) [SwiftUI Integration]( swiftui integration) [Common Mistakes]( common mistakes) [Review Checklist]( review checklist) [References]( references) Model Definition Apply @Model to a class (not struct). It synthesizes PersistentModel conformance. Model instances remain context/actor bound; pass their PersistentIdentifier , not the instance, across actors. @Attribute options : .externalStorage , .unique , .spotlight , .allowsCloudEncryption , .preserveValueOnDeletion , .ephemeral , .transformable(by:) . Rename: @Attribute(originalName: "old name") . @Relationship : deleteRule: .cascade / .nullify (default)/ .deny / .noAction . Specify inverse: for reliable behavior. Unidirectional (iOS 18+): inverse: nil . Unique (iOS 18+) : Unique<Person ([\.firstName, \.lastName]) compound uniqueness. Inheritance (iOS 26+) : @Model class BusinessTrip: Trip { var company: String } . Supported types: Bool , Int / UInt variants, Float , Double , String , Date , Data , URL , UUID , Decimal , Array , Dictionary , Set , Codable enums, Codable structs and other compatible Codable value types, and relationships to @Model classes. ModelContainer Setup CloudKit Sync ModelConfiguration(..., cloudKitDatabase:) opts a SwiftData store into automatic CloudKit sync, but app entitlements still gate sync. For any SwiftData CloudKit setup or schema review task, include a separate Capabilities verdict before schema findings: Capabilities : Xcode target has the iCloud capability with CloudKit enabled and the intended container selected, plus Background Modes Remote notifications. Without these entitlements, automatic sync is not fully configured even if cloudKitDatabase is set. Schema compatibility : no @Attribute(.unique) or Unique ; relationships are optional, have explicit inverses where needed, and avoid .deny ; large Data uses @Attribute(.externalStorage) . Scalar attributes : do not make every scalar optional just for CloudKit. Keep required scalars nonoptional when initializers, defaults, or migrations provide valid values. Schema rollout : initialize the development schema only in nonproduction builds, verify it in CloudKit Dashboard, promote before release, and treat production changes as additive only. CRUD Operations For destructive batches and migrations, first run the exact predicate or version hop against a disposable copy and record affected identifiers/counts. Execute with explicit transaction/save semantics, refetch, and verify values, relationships, counts, and invariants. On failure, fix the predicate/schema and restore a pristine fixture before retrying; never blindly replay a destructive operation. @Query in SwiftUI Predicate Supported: == , != , < , <= , , = , && , , ! , contains() , allSatisfy() , filter() , starts(with:) , localizedStandardContains() , caseInsensitiveCompare() , arithmetic, conditional expressions, optional chaining and binding, nil coalescing, type casting. Avoid : loops, nested declarations, mutations, and arbitrary unsupported method calls. FetchDescriptor Schema Versioning and Migration Lightweight handles: adding optional/defaulted properties, renaming ( originalName ), removing properties, adding model types. Verify the stage list covers every supported version hop, then migrate a fresh copy of each old store and assert post migration data before release. Core Data Coexistence Boundary Use this skill when the work is to run SwiftData alongside an existing Core Data store or migrate screens from Core Data to SwiftData over time. Keep pure Core Data stack setup, NSManagedObjectContext , NSFetchRequest , and batch Core Data operations in the sibling core data skill. For coexistence, give boundary guidance before detailed migration advice: Point SwiftData and Core Data at the same SQLite store URL. Match Core Data entity names, property names, types, and relationship shapes in the SwiftData @Model definitions. Use @Attribute(originalName:) for SwiftData properties whose persisted Core Data names differ from the Swift names. Do not write the same entity from both stacks at the same time; assign one stack as the writer for each entity during migration. Concurrency ( @ModelActor ) Rules : ModelContainer is Sendable . ModelContext is NOT use on its creating actor. Pass PersistentIdentifier (Sendable) across boundaries. Never pass @Model objects across actors. SwiftUI Integration Common Mistakes 1. @Model on struct Use class. @Model requires reference semantics. 2. @Transient without default Always provide default: @Transient var x: Bool = false . 3. Missing .modelContainer @Query returns empty without a container on the view hierarchy. 4. Passing model objects across actors: 5. ModelContext on wrong actor: 6. Unsupported Predicate expressions: 7. Flow control in Predicate: 8. No save in @ModelActor Always call try modelContext.save() explicitly. 9. ObservableObject with @Model Never use ObservableObject / @Published . @Model generates Observable . Use @Query in views. 10. Non optional relationship without default: 11. Cascade without inverse Specify inverse: for reliable cascade delete behavior. 12. DispatchQueue for background data work: Review Checklist [ ] Every @Model is a class with a designated initializer [ ] All @Transient properties have default values [ ] Relationships specify deleteRule and inverse [ ] .modelContainer attached at scene/root view level [ ] @Query used for reactive data display in SwiftUI [ ] Predicate uses only supported operators [ ] Background work uses @ModelActor [ ] PersistentIdentifier used across actor boundaries [ ] Schema changes have VersionedSchema + SchemaMigrationPlan [ ] Large data uses @Attribute(.externalStorage) [ ] CloudKit models avoid uniqueness, use optional relationships, avoid .deny , and do not blanket optionalize scalars [ ] CloudKit sync has iCloud + CloudKit, Remote notifications, and production schema rollout checked [ ] Explicit save() in @ModelActor methods [ ] Previews use ModelConfiguration(isStoredInMemoryOnly: true) [ ] @Model classes accessed from SwiftUI views are on @MainActor via @ModelActor or MainActor isolation References [references/swiftdata advanced.md](references/swiftdata advanced.md) — custom data stores, history tracking, CloudKit, composite attributes, model inheritance, undo/redo, performance [references/swiftdata queries.md](references/swiftdata queries.md) — @Query variants, FetchDescriptor deep dive, sectioned queries, dynamic queries, background fetch [references/core data coexistence.md](references/core data coexistence.md) — Core Data + SwiftData coexistence and migration boundaries [references/predicate pitfalls.md](references/predicate pitfalls.md) — Predicate runtime crashes, unsupported expressions, safe patterns [references/indexing.md](references/indexing.md) — Index macro, compound indexes, when to index, migration