SwiftData Basics
SwiftData (iOS 17+) is Apple's modern, code-first persistence framework. You'll define models with @Model , set up a ModelContainer , fetch with @Query , insert and delete objects, and see how it improves on Core Data.
Learn SwiftData Basics in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
- • Define a persistent model with the @Model macro
- • Configure storage with a ModelContainer
- • Fetch and observe data using @Query
- • Insert and delete objects via the ModelContext
- • Read the context from the SwiftUI environment
- • Compare SwiftData with Core Data (iOS 17+)
📊 SwiftData Building Blocks
Piece
Role
@Model
Makes a class persistent
ModelContainer
Sets up storage
ModelContext
Insert / delete workspace
@Query
Fetch and observe models
1️⃣ Define a Model with @Model
A SwiftData model is just a class with the @Model macro. The macro adds persistence and change tracking — no separate model file, no setValue(forKey:) .
2️⃣ Set Up the Container
Attach a ModelContainer once at the app root with .modelContainer(for:) . Views then read the active ModelContext from the environment.
Your turn. Fill in the macro and the model type.
3️⃣ Query, Insert, and Delete
@Query fetches models with type-safe sorting and keeps the view in sync. Use context.insert(_:) to add and context.delete(_:) to remove.
Now you try. Fill in the insert and delete methods.
Pro Tips
- 💡 List every model type in .modelContainer(for:) or it won't be stored.
- 💡 Sort with key paths, e.g. @Query(sort: \\Task.title) — type-safe and refactor-friendly.
- 💡 SwiftData often autosaves, so you rarely call save() yourself.
- 💡 Target iOS 17+; fall back to Core Data when you must support older systems.
Common Errors (and the fix)
- Objects never persist — you didn't attach a .modelContainer(for:) for the type.
- "@Model requires a class" — apply the macro to a final class , not a struct.
- List doesn't update — fetch with @Query , not a manual array.
- "Available in iOS 17 or newer" — SwiftData needs an iOS 17+ deployment target.
📋 Quick Reference
Task
Code
Result
Model
@Model final class Task
persistent
Storage
.modelContainer(for: Task.self)
sets up store
Fetch
@Query var tasks: [Task]
live results
Add
context.insert(task)
new object
Remove
context.delete(task)
removed
Frequently Asked Questions
Mini-Challenge: SwiftData To-Do
Build a small @Model-backed to-do list with @Query, insert, and delete — and notice how little code it takes.
🎉 Lesson Complete!
- ✅ @Model makes a Swift class persistent — no model file
- ✅ A ModelContainer sets up storage at the app root
- ✅ @Query fetches and observes models with type-safe sorting
- ✅ context.insert(_:) and context.delete(_:) add and remove
- ✅ SwiftData is the code-first, less-boilerplate successor to Core Data (iOS 17+)
- ✅ Next lesson: Unit Testing with XCTest
Practice quiz
Which macro marks a class as a SwiftData model?
- @State
- @Model
- @Entity
- @Persisted
Answer: @Model. @Model turns a class into a persistent SwiftData model.
From which iOS version is SwiftData available?
- iOS 13
- iOS 15
- iOS 17
- iOS 11
Answer: iOS 17. SwiftData was introduced with iOS 17.
What sets up SwiftData's storage for your app?
- NSPersistentContainer
- ModelContainer
- URLSession
- ModelView
Answer: ModelContainer. A ModelContainer configures and holds SwiftData's storage.
Which property wrapper fetches and observes model objects in a view?
- @FetchRequest
- @Query
- @Published
- @Binding
Answer: @FetchRequest. @Query loads SwiftData models and keeps the view updated.
Which context method adds a new model object?
- context.insert(object)
- context.add(object)
- context.append(object)
- context.push(object)
Answer: context.insert(object). modelContext.insert(_:) inserts a new object into the store.
Which context method removes a model object?
- context.remove(object)
- context.discard(object)
- context.drop(object)
- context.delete(object)
Answer: context.delete(object). modelContext.delete(_:) removes the object.
Compared with Core Data, SwiftData models are defined using...
- An .xcdatamodeld editor
- Plain Swift classes with @Model
- JSON files
- Property lists
Answer: Plain Swift classes with @Model. SwiftData uses code-first @Model classes instead of a visual model editor.
How do you reach the model context inside a SwiftUI view?
- @State var context
- @Environment(\.modelContext)
- URLSession.shared
- @Binding context
Answer: @Environment(\.modelContext). @Environment(\.modelContext) provides the active context to the view.
What is SwiftData built on top of?
- Realm
- Core Data's proven engine
- SQLite only, no framework
- UserDefaults
Answer: Core Data's proven engine. SwiftData is a modern Swift API layered over Core Data's engine.
A key advantage of SwiftData over Core Data is...
- It needs Objective-C
- It cannot persist data
- It only works on macOS
- A type-safe, code-first Swift API with less boilerplate
Answer: A type-safe, code-first Swift API with less boilerplate. SwiftData offers a cleaner, type-safe Swift-native API with far less boilerplate.
Continue this course
- Previous: Persistence with Core Data
- Next: Unit Testing with XCTest