How to connect SwiftData to SwiftUI
2023년 9월 22일About 2 min
How to connect SwiftData to SwiftUI 관련
SwiftData by Example
Back to Home
How to connect SwiftData to SwiftUI | SwiftData by Example
How to connect SwiftData to SwiftUI
Updated for Xcode 15
SwiftData was built with SwiftUI in mind, and it integrates tightly into SwiftUI views. This takes a number of forms:
- The
@Query
macro queries SwiftData objects, and automatically stays updated as those objects change. This macro works only on SwiftUI views. - We can inject one or more SwiftData model contains directly into the environment using the
modelContainer()
modifier. This will create the database if it isn't there, or load an existing one that was created previously. - Although each SwiftUI view can have only one model container, we can attach different model containers to different views in our hierarchy.
- We have a
.modelContext
environment key to read the main context, which automatically uses the main actor to make data manipulation safe from views. This is the same model context used by any@Query
properties in that view.
We can put all the core components together in some sample code, starting with two models to store authors and the books they have written:
@Model
class Author {
var name: String
var books: [Book]
init(name: String, books: [Book]) {
self.name = name
self.books = books
}
}
@Model
class Book {
var title: String
var author: Author?
init(title: String, author: Author? = nil) {
self.title = title
self.author = author
}
}
We could then show a list of authors and their books using @Query
in a SwiftUI view, such as this one:
struct AuthorsView: View {
@Query(sort: \Author.name) var authors: [Author]
var body: some View {
NavigationStack {
List(authors) { author in
Text(author.name)
Text(author.books.map(\.title).formatted(.list(type: .and)))
}
.navigationTitle("iLibrary")
}
}
}
And finally, tie it all together in our App
struct, using the modelContainer(for:)
modifier:
@main
struct LibraryApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: [Author.self, Book.self])
}
}
Note
Because Author
and Book
share a relationship, we can use either modelContainer(for: Author.self)
or modelContainer(for: Book.self)
and have SwiftData automatically load both models.