-
Dive deeper into SwiftData
Learn how you can harness the power of SwiftData in your app. Find out how ModelContext and ModelContainer work together to persist your app's data. We'll show you how to track and make your changes manually and use SwiftData at scale with FetchDescriptor, SortDescriptor, and enumerate.
To get the most out of this session, we recommend first watching "Meet SwiftData" and "Model your schema with SwiftData" from WWDC23.Chapitres
- 0:00 - Intro
- 3:42 - Configuring persistence
- 7:21 - Track and persist changes
- 11:20 - Modeling at scale
- 14:54 - Wrap-up
Ressources
Vidéos connexes
WWDC23
-
Rechercher dans cette vidéo…
-
-
1:45 - Trip model with cascading relationships
@Model final class Trip { var destination: String? var end_date: Date? var name: String? var start_date: Date? @Relationship(.cascade) var bucketListItem: [BucketListItem] = [BucketListItem]() @Relationship(.cascade) var livingAccommodation: LivingAccommodation? } -
4:21 - Initializing a ModelContainer
// ModelContainer initialized with just Trip let container = try ModelContainer(for: Trip.self) // SwiftData infers related model classes as well let container = try ModelContainer( for: [ Trip.self, BucketListItem.self, LivingAccommodation.self ] ) -
5:41 - Using ModelConfiguration to customize ModelContainer
let fullSchema = Schema([ Trip.self, BucketListItem.self, LivingAccommodations.self, Person.self, Address.self ]) let trips = ModelConfiguration( schema: Schema([ Trip.self, BucketListItem.self, LivingAccommodations.self ]), url: URL(filePath: "/path/to/trip.store"), cloudKitContainerIdentifier: "com.example.trips" ) let people = ModelConfiguration( schema: Schema([Person.self, Address.self]), url: URL(filePath: "/path/to/people.store"), cloudKitContainerIdentifier: "com.example.people" ) let container = try ModelContainer(for: fullSchema, trips, people) -
6:49 - Creating ModelContainer in SwiftUI
@main struct TripsApp: App { let fullSchema = Schema([ Trip.self, BucketListItem.self, LivingAccommodations.self, Person.self, Address.self ]) let trips = ModelConfiguration( schema: Schema([ Trip.self, BucketListItem.self, LivingAccommodations.self ]), url: URL(filePath: "/path/to/trip.store"), cloudKitContainerIdentifier: "com.example.trips" ) let people = ModelConfiguration( schema: Schema([ Person.self, Address.self ]), url: URL(filePath: "/path/to/people.store"), cloudKitContainerIdentifier: "com.example.people" ) let container = try ModelContainer(for: fullSchema, trips, people) var body: some Scene { WindowGroup { ContentView() } .modelContainer(container) } } -
7:40 - Using the modelContainer modifier
@main struct TripsApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(for: Trip.self) } } -
7:50 - Referencing a ModelContext in SwiftUI views
struct ContentView: View { @Query var trips: [Trip] @Environment(\.modelContext) var modelContext var body: some View { NavigationStack (path: $path) { List(selection: $selection) { ForEach(trips) { trip in TripListItem(trip: trip) .swipeActions(edge: .trailing) { Button(role: .destructive) { modelContext.delete(trip) } label: { Label("Delete", systemImage: "trash") } } } .onDelete(perform: deleteTrips(at:)) } } } } -
9:57 - Enabling undo on a ModelContainer
@main struct TripsApp: App { @Environment(\.undoManager) var undoManager var body: some Scene { WindowGroup { ContentView() } .modelContainer(for: Trip.self, isUndoEnabled: true) } } -
11:05 - Enabling autosave on a ModelContainer
@main struct TripsApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(for: Trip.self, isAutosaveEnabled: false) } } -
11:54 - Fetching objects with FetchDescriptor
let context = self.newSwiftContext(from: Trip.self) var trips = try context.fetch(FetchDescriptor<Trip>()) -
12:14 - Fetching objects with #Predicate and FetchDescriptor
let context = self.newSwiftContext(from: Trip.self) let hotelNames = ["First", "Second", "Third"] var predicate = #Predicate<Trip> { trip in trip.livingAccommodations.filter { hotelNames.contains($0.placeName) }.count > 0 } var descriptor = FetchDescriptor(predicate: predicate) var trips = try context.fetch(descriptor) -
12:27 - Fetching objects with #Predicate and FetchDescriptor
let context = self.newSwiftContext(from: Trip.self) predicate = #Predicate<Trip> { trip in trip.livingAccommodations.filter { $0.hasReservation == false }.count > 0 } descriptor = FetchDescriptor(predicate: predicate) var trips = try context.fetch(descriptor) -
13:18 - Enumerating objects with FetchDescriptor
context.enumerate(FetchDescriptor<Trip>()) { trip in // Operate on trip } -
13:36 - Enumerating with FetchDescriptor and SortDescriptor
let predicate = #Predicate<Trip> { trip in trip.bucketListItem.filter { $0.hasReservation == false }.count > 0 } let descriptor = FetchDescriptor(predicate: predicate) descriptor.sortBy = [SortDescriptor(\.start_date)] context.enumerate(descriptor) { trip in // Remind me to make reservations for trip } -
14:01 - Fine tuning enumerate with batchSize
let predicate = #Predicate<Trip> { trip in trip.bucketListItem.filter { $0.hasReservation == false }.count > 0 } let descriptor = FetchDescriptor(predicate: predicate) descriptor.sortBy = [SortDescriptor(\.start_date)] context.enumerate( descriptor, batchSize: 10000 ) { trip in // Remind me to make reservations for trip } -
14:28 - Fine tuning enumerate with batchSize and allowEscapingMutations
let predicate = #Predicate<Trip> { trip in trip.bucketListItem.filter { $0.hasReservation == false }.count > 0 } let descriptor = FetchDescriptor(predicate: predicate) descriptor.sortBy = [SortDescriptor(\.start_date)] context.enumerate( descriptor, batchSize: 500, allowEscapingMutations: true ) { trip in // Remind me to make reservations for trip }
-