Open menu with table of contents Working with SwiftData
Logo of Stuttgart Media University for light theme Logo of Stuttgart Media University for dark theme
Mobile Application Development 2

Working with SwiftData

Stuttgart Media University

1 Agenda

  • Introduction to SwiftData
  • Model Macro
  • Model Container
  • Fetching Data

2 Model Macro @Model

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]? = []
}

3 Model Properties

Attributes are inferred from properties Support for basic value types and more complex value types, e.g.:

  • Struct
  • Enum
  • Codable
  • Collections of value types

4 Model Relationships

Relationships are inferred from reference types

  • Other model types
  • Collection of model types

5 Additional Metadata Macros

Control how properties are inferred by using

@Attribute @Relationship

Exclude properties with @Transient

6 Example Metadata

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]? = []
}

7 Model Container

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))

8 Creating a Model Container with Context

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])
    }
}

9 Model Context

Model Contexts observe all changes on your models. They are responsible for:

  • Tracking updates
  • Fetching models
  • Saving changes
  • Undoing changes

10 Model Context in SwiftUI

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
}

11 Fetching Data

With a model context you can fetch data. Swift defines native types for this:

  • Predicate
  • FetchDescriptor
  • SortDescriptor

12 Predicates

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
}

13 FetchDescriptor

Fetching data is done using a FetchDescriptor and the Predicate:


let descriptor = FetchDescriptor<Lecture>(predicate: lecturePredicate)

let lectures = try context.fetch(descriptor)

14 SortDescriptor

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:

  • Relationships to prefetch
  • Result limits
  • Exclude unsaved changes

15 Insert, Delete, Save Data

15.1 Insert


var myLecture = Lecture(name: "Mobile Application Development, lecturer: "Ansgar Gerlicher")
// ...

context.insert(myLecture)

15.2 Delete


context.delete(myLecture)

15.3 Save


context.save(myLecture)

16 Using Query in SwiftUI

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
                    // ...
                }
            }
        }
    }
}

17 Observing Changes in SwiftUI with SwiftData

SwiftUI will automatically refresh changes in the observed properties. No need for @Published.

18 Conclusion

Steps to use SwiftData:

  • Use @Model to setup the schema
  • Configure the ModelContainer
  • Use SwiftData with @Environment and @Query in SwiftUI Views