Chapters
0:00 - Intro
1:07 - Using the model macro
3:17 - Working with your data
7:02 - Use SwiftData with SwiftUI
8:10 - Wrap-up

Intro
Using the model macro
Working with your data
Use SwiftData with SwiftUl
SwiftData is a powerful framework for data modeling and management. It uses Swift’s new macro system to create a seamless API experience. It is naturally integrated with SwiftUI and works with other platform features, like CloudKit and Widgets.
Using the model macro
@Model
Powerful new Swift macro
Define your schema with code
Add SwiftData functionality to model types
Add import SwiftData and @Model to the model class and the schema is generated.
// Adding @Model to Trip
import SwiftData
@Model
class Trip {
var name: String
var destination: String
var endDate: Date
var startDate: Date
var bucketList: [BucketListItem]? = []
var livingAccommodation: LivingAccommodation?
}Models in SwiftData are the source of truth and will transform the class’ stored properties into persisted properties.
Attributes
SwiftData natively adapts value type properties to be used as attributes. These properties include basic value types, like string, int, and float. They can also include more complex value types, such as structs, enums, and codable types too, including collections.
Relationships
Relationships are inferred from reference types
Other model types
Collections of model types
SwiftData models reference types as relationships.
Additional Metadata
@Attribute(.unique)for uniqueness constraint@Relationshipfor choice of inverses and delete propagation rules@Transientto exclude property from model
Here is an example.
// Providing additional metadata
import SwiftData
@Model
class Trip {
@Attribute(.unique) var name: String
var destination: String
var endDate: Date
var startDate: Date
@Relationship(.cascade) var bucketList: [BucketListItem]? = []
var livingAccommodation: LivingAccommodation?
}To learn more about SwiftData modeling, check out the session:
Model your schema with SwiftData - WWDC23
Working with your data
Model container
The Model container provides the persistent backend
Customized with configurations. Use the default settings just by specifying the schema.
Provides schema migration options
Create a container by specifying the list of model types to store
optionally provide
ModelConfigurationwith an url, CloudKit and group container identifiers, and migration options
let container = try ModelContainer(for: [Trip.self, LivingAccommodation.self], configurations: ModelConfiguration(url: URL("path")))Or in SwiftUI with the modifier
.modelContainer(for: [Trip.self, LivingAccommodation.self])`ModelContext
With the container set up, fetch and save data with model contexts. Also can be used with a SwiftUI’s view and scene modifiers to set up a container and have it in the view’s environment.
import SwiftData
import SwiftUI
@main
struct TripsApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for:
[Trip.self,
LivingAccommodation.self])
)
}
}Model contexts observe all the changes to the models and provide many of the actions to operate on them.
Tracking updates
Fetching models
Saving changes
Undoing changes
In SwiftUI, generally the modelContext is from the view’s environment.
import SwiftData
import SwiftUI
struct ContextView : View {
@Environment(\.modelContext) private var context
}
// or outside the view hierarchy, a shared main actor bound context,
let context = container.mainContext
// or instantiate new contexts for a given model container.
let context = ModelContext(container)Fetching Data
New in iOS 17, predicate works with native Swift types and uses Swift macros for strongly typed construction. It’s a modern replacement for NSPredicate.
New Swift native types:
Predicate
FetchDescriptor
Improvements to SortDescriptor
Predicate
Fully type checked.
#Predicateconstruction instead of text parsingAutocompleted keypaths.
Here are a few examples of building predicates.
// I can specify all the trips whose destination is New York.
let tripPredicate = #Predicate<Trip> {
$0.destination == "New York"
}
// I can narrow our query down to just trips about birthdays
let tripPredicate = #Predicate<Trip> {
$0.destination == "New York" && $0.name.contains("birthday")
}
// and I can specify we're only interested in trips planned for the future, as opposed to any of our past adventures.
let today = Date()
let tripPredicate = #Predicate<Trip> {
$0.destination == "New York" &&
$0.name.contains("birthday") &&
$0.startDate > today
}We can use the new FetchDescriptor type and instruct our ModelContext to fetch those trips.
let descriptor = FetchDescriptor<Trip>(predicate: tripPredicate)
let trips = try context.fetch (descriptor)SortDescriptor
Updated to support all Comparable types
Swift native keypaths..
Swift SortDescriptor works together with FetchDescriptor and is getting some updates to support native Swift types and keypaths
let descriptor = FetchDescriptor<Trip>(
sortBy: SortDescriptor(\Trip.name),
predicate: tripPredicate
)
let trips = try context.fetch(descriptor)More FetchDescriptor options
relationships to prefetch
result limits
exclude unsaved changes and more
Modifying Data
Basic operations
Inserting
Deleting
Saving
Changing
Delete persistent objects marking them for deletion, and committing them to the persistent container.
var myTrip = Trip(name: "Birthday Trip", destination: "New York")
// Insert a new trip
context.insert(myTrip)
// Delete an existing trip
context.delete(myTrip)
// Manually save changes to the context
try context.save()The
@Modelmacro modifies stored properties for change tracking and observationUpdated automatically by the ModelContext
To learn more about SwiftData containers and contexts and driving its operations, check out the session:
Dive deeper into SwiftData - WWDC23
Use SwiftData in SwiftUI
Seamless integration with SwiftUI
Easy configuration
Automatically fetch data and update views
View modifiers
Configure data store with
.modelContainerwhich is propagated throughout SwiftUI environmentFetching in SwiftUI with
@QueryNo need for
@Publishedand SwiftUI automatically updates
// @Query
import SwiftData
import SwiftUI
struct ContentView: View {
@Query(sort: \.startDate, order: .reverse) var trips: [Trip]
@Environment(\.modelContext) var modelContext
var body: some View {
NavigationStack() {
List {
ForEach(trips) { trip in
// ...
}
}
}
}
}Observing changes
No need for @Published
SwiftUl automatically refreshes
SwiftData supports the all-new observable feature for your modeled properties. SwiftUI will automatically refresh changes on any of the observed properties. SwiftUI and SwiftData work hand in hand
Learn more about using these frameworks together in our session:
Build an app with SwiftData - WWDC23

Resources
Adopting SwiftData for a Core Data app
Have a question? Ask with tag wwdc2023-10187
Search the forums for tag wwdc2023-10187
SwiftData
Related Videos
Build an app with SwiftData - WWDC23
Discover Observation in SwiftUI - WWDC23
Dive deeper into SwiftData - WWDC23
Migrate to SwiftData - WWDC23
Model your schema with SwiftData - WWDC23
What’s new in Swift - WWDC23
What’s new in SwiftUI - WWDC23

