Allows you to define your schema with code and adds SwiftData functionality to your model types.
Example:
import SwiftData
@Model
class Lecture {
var name: String
var lecturer: String
var startDate: Date
var lenghtInMinutes: Int
var contents: [LectureContents]? = []
}
Attributes are inferred from properties Support for basic value types and more complex value types, e.g.:
Relationships are inferred from reference types
Control how properties are inferred by using
@Attribute @Relationship
Exclude properties with @Transient
import SwiftData
@Model
class Lecture {
// Unique - acts as primary key
@Attribute(.unique) var name: String
var lecturer: String
var startDate: Date
var lenghtInMinutes: Int
// Instructs SwiftData to delete all related
// items when this Lecture is deleted
@Relationship(.cascade) var contents: [LectureContents]? = []
}
Provides the persistent backend for model types Customizable with configurations and migration options
import SwiftData
let container = try ModelContainer(for: [Lecture.self, LectureContents.self],
configurations: ModelConfiguration(isStoredInMemoryOnly: true))
Example how a Model Container is added to your app and make it accessible in your views environment for SwiftUI views:
import SwiftUI
import SwiftData
@main
struct LectureApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: [Lecture.self, LectureContent.self])
}
}
Model Contexts observe all changes on your models. They are responsible for:
To use the model context in SwiftUI you generally use the @Environment macro like this:
import SwiftData
import SwiftUI
struct ContentView : View {
@Environment(.\modelContext) private var context
}
With a model context you can fetch data. Swift defines native types for this:
A #Predicate allows you to filter data based on attributes. E.g.:
let today = Date()
let lecturePredicate = #Predicate<Lecture> {
$0.lecturer.contains("Gerlicher") &&
$0.lenghtInMinutes == 90 &&
$0.startDate > today
}
Fetching data is done using a FetchDescriptor and the Predicate:
let descriptor = FetchDescriptor<Lecture>(predicate: lecturePredicate)
let lectures = try context.fetch(descriptor)
A SortDescriptor allows to sort your data:
let descriptor = FetchDescriptor<Lecture>(sortBy: SortDescriptor(\Lecture.startDate), predicate: lecturePredicate)
let lectures = try context.fetch(descriptor)
FetchDescriptor also allows to define:
var myLecture = Lecture(name: "Mobile Application Development, lecturer: "Ansgar Gerlicher")
// ...
context.insert(myLecture)
context.delete(myLecture)
context.save(myLecture)
Use the @Query property wrapper in a SwiftUI view to access data
import SwiftData
import SwiftUI
struct ContentView : View {
@Query(sort: \.startDate, order: .reverse) var lectures: [Lecture]
@Environment(.\modelContext) private var context
var body: some View {
NavigationStack() {
List {
ForEach(lectures) { lecture in
// ...
}
}
}
}
}
SwiftUI will automatically refresh changes in the observed properties. No need for @Published.
Steps to use SwiftData: