WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

Storing our data with SwiftData

Paul Hudson    @twostraws   

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.

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.0/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.