Lots of apps are great candidates for SwiftData, and most of the time it takes surprisingly little work to get it all set up.
In our app we have a TabView
that contains three instances of ProspectsView
, and we want all three of those to work as different views on the same shared data. In SwiftData terms, this means they all access the same model context, but using slightly different queries.
So, start by making a new Swift file called Prospect.swift, replacing its Foundation import with SwiftData, then giving it this code:
@Model
class Prospect {
var name: String
var emailAddress: String
var isContacted: Bool
}
Once you have that, just type in
below the isContacted
property to have Xcode autocomplete the initializer for you.
Remember, SwiftData's @Model
macro can only be used on a class, but it means we can share instances of that object in several views to have them all kept up to date automatically.
Now that we have something to store, we can tell SwiftData to create a model container for it. This means going to HotProspectsApp.swift, giving it an import for SwiftData, then adding the modelContainer(for:)
modifier like this:
WindowGroup {
ContentView()
}
.modelContainer(for: Prospect.self)
That creates storage for our Prospect
class, but also places a shared SwiftData model context into every SwiftUI view in our app, all with one line of code.
We want all our ProspectsView
instances to share that model data, so they are all pointing to the same underlying data. This means adding two properties: one to access the model context that was just created for us, and one to perform a query for Prospect
objects.
So, go ahead and open ProspectsView.swift, give it an import for SwiftData, then add these two new properties to the ProspectsView
struct:
@Query(sort: \Prospect.name) var prospects: [Prospect]
@Environment(\.modelContext) var modelContext
Tip: If you intend to use Xcode's previews, add modelContainer(for: Prospect.self)
to your preview code.
That really is all it takes – I don’t think there’s a way SwiftData could make this any easier.
Soon we’re going to be adding code to add prospects by scanning QR codes, but for now we’re going to add a navigation bar item that just adds test data and shows it on-screen.
Change the body
property of ProspectsView
to this:
NavigationStack {
Text("People: \(prospects.count)")
.navigationTitle(title)
.toolbar {
Button("Scan", systemImage: "qrcode.viewfinder") {
let prospect = Prospect(name: "Paul Hudson", emailAddress: "paul@hackingwithswift.com", isContacted: false)
modelContext.insert(prospect)
}
}
}
Now you’ll see a “Scan” button on the first three views of our tab view, and tapping it adds a person to all three simultaneously – you’ll see the count increment no matter which button you tap.
SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure and A/B test your entire paywall UI without any code changes or app updates.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.