In this demo, you’ll finish updating TheMet app to use multiple data management patterns. You’ll analyze what technologies the app is using, and look to see if any improvements can be made.
Open TheMet app in the Starter folder.
You’ll work through another hypothetical situation in this demo. In this situation, the business has been impressed with your previous efforts in handling data management in the app. You’ve been given the responsibility to ensure all data in the app is managed in the best way, by introducing a data strategy and making recommendations for improvements.
Let’s start by reviewing the app. First, open the MetView file and take time to inspect the data sources feeding the file.
You can see that the view deals with a modelContext and a @Query property wrapper from Swift Data. Swift Data reads and writes MetQuery objects, which are used to store previous query searches.
Take a look at how modelContext is used in the app on line 82.
Button("Search the Met") {
modelContext.insert(MetQuery(query: currentMetQuery))
showQueryField = true
}
The modelContext is writing a MetQuery to Swift Data. While this works, it can be improved. For instance, this data management pattern can be improved by moving the call to a better place that isn’t responsible for rendering UI.
Let’s do that now. Open the TheMetStore file, create a new function called addMetQuery(), and pass the query as the parameter. Add the modelContext.insert() line into the function.
func addMetQuery(currentMetQuery: String) {
modelContext.insert(MetQuery(query: currentMetQuery))
}
Xcode will show an error because it can’t find modelContext in the file, let’s fix that now.
Add the modelContext property to TheMetStore and update the initializer so you can pass in the modelContext.
private let modelContext: ModelContext
init(modelContext: ModelContext,_ maxIndex: Int = 30) {
self.modelContext = modelContext
self.maxIndex = maxIndex
}
While you’re here, also update the file so it uses the @Observable macro. This updates the TheMetStore to use the latest approach to observability using the observation framework.
@Observable
class TheMetStore {
var objects: [Object] = []
private let service = TheMetService()
private let maxIndex: Int
private let modelContext: ModelContext
// ... more code below ...
With the file updated, move to the MetView file and handle the errors there. Update the store property on line 48 so it uses the @State property wrapper.
@State private var store: TheMetStore
Next, add an initializer to the file so modelContext can be passed into the file and also passed into TheMetStore.
init(modelContext: ModelContext) {
let store = TheMetStore(modelContext: modelContext)
_store = State(initialValue: store)
}
To finish, remove the modelContext passed in via the environment property on line 38. Then remove the modelContext.insert() call on line 86.
The work for this file is done, however because MetView now receives the modelContext as a parameter, the preview requires to be updated. Let’s do that:
#Preview {
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try! ModelContainer(for: MetQuery.self, configurations: config)
return MetView(modelContext: container.mainContext)
}
Next, let’s move to the TheMetApp file. Open TheMetApp and add an initializer to set up the ModelContainer.
init() {
do {
container = try ModelContainer(for: MetQuery.self)
} catch {
fatalError("Failed to create ModelContainer.")
}
}
Finally, add a property to store the container and pass it into the MetView() and modelContainer properties.
let container: ModelContainer
var body: some Scene {
WindowGroup {
MetView(modelContext: container.mainContext).modelContainer(container)
}
}
Run the app, and you’ll see the app works as before. This time though, it’s using the data patterns you improved. You moved the modelContext to be used in TheMetStore, and also updated the TheMetStore to use the new Observation Framework.
If you take a look at a few other parts of the app, you can identify a couple of the other data management patterns in place. App Storage is used in TheMetView to store the last query for easy reading.
You can also see TheMetService is using NSCache to store previous network responses.
These look like good data management patterns, so you can begin to say that the app is using a well-defined data strategy that the team can rely on. Your work is done, and you can report back to the business about your findings and improvements!