Swiftdata pro
Skill laxrajpurohit/swift-skills-pro/swiftdata-pro/skills/swiftdata-pro
Modern, original agent skills for Swift and Apple-platform development
npx -y skills add laxrajpurohit/swift-skills-pro --skill swiftdata-proAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when modeling data with SwiftData (@Model), writing @Query, configuring ModelContainer, performing migrations, or enabling CloudKit sync on iOS 17+.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
3.6 KB, as published. Nobody here has run it
SwiftData Pro
Model, query, and persist data with SwiftData correctly and efficiently.
When to use
- Defining
@Modeltypes and relationships. - Writing
@Query/ fetching in views. - Setting up
ModelContainer, migrations, or CloudKit sync.
Trigger: /swiftdata-pro.
Core principles
@Modelclasses are reference types managed by aModelContext.- Inject the container at the app root with
.modelContainer(for:). - Read in views with
@Query; write through themodelContext. - Keep the main-actor context for UI; use a background
ModelContextfor bulk work.
Modeling
@Model
final class Trip {
var name: String
var startDate: Date
@Relationship(deleteRule: .cascade) var stops: [Stop] = []
init(name: String, startDate: Date) {
self.name = name
self.startDate = startDate
}
}
- Set an explicit
deleteRuleon relationships — don't rely on defaults for ownership. - Use
@Attribute(.unique)for natural keys. - Mark large blobs
@Attribute(.externalStorage).
❌ No delete rule on an owning relationship
var stops: [Stop] = [] // orphans Stop rows when a Trip is deleted
✅
@Relationship(deleteRule: .cascade) var stops: [Stop] = []
Container setup
@main
struct TripsApp: App {
var body: some Scene {
WindowGroup { ContentView() }
.modelContainer(for: Trip.self)
}
}
Querying
Use @Query with sort/filter in the view; don't fetch-all then filter in Swift.
❌
@Query private var trips: [Trip]
var upcoming: [Trip] { trips.filter { $0.startDate > .now } } // loads everything
✅
@Query(filter: #Predicate<Trip> { $0.startDate > Date.now },
sort: \Trip.startDate)
private var upcoming: [Trip]
Writing
@Environment(\.modelContext) private var context
func add(_ trip: Trip) {
context.insert(trip)
// SwiftData autosaves; call try? context.save() only when you need it now.
}
Delete with context.delete(trip).
Background work
For imports/bulk writes, use a separate context off the main actor and save in batches:
let context = ModelContext(container)
for row in rows { context.insert(Item(row)) }
try context.save()
Don't do thousands of inserts on the main-actor context — it blocks the UI.
Migrations
- Lightweight changes (adding optional properties) migrate automatically.
- Breaking changes need a
SchemaMigrationPlanwith versioned schemas and migration stages. DefineVersionedSchematypes; never silently mutate a shipped model.
CloudKit sync
- Every property must be optional or have a default; relationships must be optional.
- No
@Attribute(.unique)(CloudKit can't enforce it). - Configure with a
ModelConfigurationusing a CloudKit container identifier.
❌ (breaks CloudKit)
@Attribute(.unique) var code: String
✅
var code: String = ""
Common mistakes checklist
- Missing
deleteRuleon owning relationships. - Filtering fetched arrays in Swift instead of
#Predicatein@Query. - Bulk inserts on the main-actor context.
-
.uniqueor non-optional properties on a CloudKit-synced model. - Breaking schema change with no migration plan.
Output format (when reviewing)
Per issue: file:line, rule, before/after. Lead with data-loss / migration risks.