Getting Started With SwiftData
Apple introduced SwiftData as a built-in feature for Swift and an evolution of Core Data. While not technically true, you could say that SwiftData sits on top of Core Data to make reasoning about SwiftData easier.
Like many of the older tools, Core Data was described using XML, where SwiftData is written and described in the more approachable Swift language. One of the biggest conveniences of using SwiftData and Core Data is how they both handle the standard CRUD (Create, Read, Update, Delete) operations needed for saving data without requiring any additional work by you.
With the addition of Swift Macros, Apple has packaged SwiftData instructions into single commands.
First up, the @Model macro transforms your model class into a SwiftData model by packing in the PersistentModel protocol. The PersistentModel also includes the Observable, Hashable and Identifiable protocols. If you’ve done any work with data and lists, you’ll recognize these protocols for iterating through, comparing, and indexing data types. The @Model macro packs quite a punch in capabilities.
Note: To persist means to continue to survive or exist. Your app’s data will be preserved between app launches, when you lose power, and shut down your device. With the right setup, your data can even be synced between your own devices.
Next in the SwiftData arsenal, is the ModelContainer. This tool takes the model and data values, then combines them into data objects. The ModelContainer can set up data, load the data for the app to use, and stores the persisted data in the data stores.
The third tool is the ModelContext which acts like a note pad for SwiftData. The ModelContext is a space allocated in memory to store the readable data, changed data, deleted data, undo, and redo data. The data stays in the ModelContext and is saved to the store periodically. This happens so quickly that you don’t need to think about it. During development you’ll spend a lot of time with the ModelContext.
Note: The ability to have undo and redo requires enabling an environment property. You’ll learn about that in a future lesson.
There are a few more macros you’ll employ with SwiftData, and you’ll learn to use them in future lessons. The @Attribute macro is applied to a single property in the data model. With this macro, you can mark a property as .unique where you only want one entry, such as a country name or city. The .ephemeral attribute prevents persistence. .externalStorage is used to persist large data types, like images or binary data.
Smaller images get saved in the store, but others are saved as references to an external location. If you’ve used SwiftData in Xcode 15, you’ll have used the #Preview macro with your Canvas pane in Xcode. You can provide in-memory mock data for your previews as you work.
The @ModelActor macro is used to run code on the application’s main thread, which can be important when updating the state of data in your views. You’ll meet the #Predicate macro later when you’ll learn how to filter and search through your data.
@Query is a new property wrapper that fetches all of the model-related data for your view. You’ll use this a lot as it’s quite a workhorse for fetching, sorting, and filtering data. SwiftData also includes a new @Environment(.\modelContext) variable that you’ll use when you want to create and update objects in your views.
That’s a lot of new concepts to try to absorb, but you’ll start with the basics first.
In this lesson, you’ll learn how to set up your model for SwiftData, see how to display your data in a SwiftUI view, create new data objects, delete data, and work with mock data in the Simulator and on a device if you like.
You’ll be building an app called GoodDog to keep track of your furry canine friends. Continue on to the demo.