One thing we iOS developers should rejoice about is the development of SwiftData, at least if you are coding for a very new project and can forget about iOS versions below 17.
We finally have an encapsulations (of sorts) of the more complex Core Data engine , and it even integrates seamlessly with our Beloved SwiftUI.
SwiftData is a powerful and expressive persistence framework built for Swift. We’ll show you how you can model your data directly from Swift code, use SwiftData to work with your models, and integrate with SwiftUI.
import SwiftData
@Model
class Hiking {
var start: Date
var end: Date
var distance: Double
}
There you have a class that has all the main database "CRUD" operations: Create, Read, Update and Delete.
SwiftData model Queries Wrappers
SwiftData includes the @Query
macro as a new property wrapper meant specifically for SwiftData.
struct HikingListView: View {
@Query (sort, .started) var hikings: [Hiking]
body: some View {
ForEach(hikings) {
// Show off your outdoors and active lifestyle here </joke>
}
}
Every view can have as many query properties as it needs. Under the hood it uses the ModelContext
of the view as its source of data.
This ModelContext
comes from the ModelContainer
. Each SwiftUI app must provide at least one ModelContainer
as an environment variable.
import SwiftData
@mainstruct SwiftHikingApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer (for: Hiking.self, Location.self )
}
}
Let’s say you also want to highlight specific locations in a hiking, we could use the following code:
import SwiftData
@Modelclass Hiking {
var start: Date
var end: Date
var distance: Double
@Relationship(deleteRule: .cascade) var locations: [Location] = []
}
@Modelclass Location {
var name: String
var images: [Strings]
}
This way, simply creating or removing a location takes effect immediate in your app:
ForEach(hikings) { hiking in
VStack {
Text(hiking.description)
Spacer()
ForEach(hiking.locations) { location in
NavigationLink { destination in
DestinationRow(destination)
} { Text("67% complete") }
}
}
//**************************************
.onDelete(perform: { indexSet in
if let index = indexSet.first {
hiking.locations.remove(at: index
)
}
// *************************************}
}
Notice how we only need to remove a Location from the Hikings arrays of them. This can make your life much easier but it's important to focus on small details, since merely removing a location from a hiking model will remove it from the database.
Compare it with the snipped where we delete a hiking:
private func deleteHiking(_ indexSet: IndexSet) {
for index in indexSet {
let hiking = hikings[index]
modelContext.delete(hiking)
}
}
That's how easy it is to use the basic functions of SwiftData. Don't forget to declare the relationships between Hiking and locations. It's a great choice to store data if you only need to support iOS 16 or newer. It may not be such a great choice if you need all the functionalities and robustness of CoreData, some of which are probably not available for SwiftData as of yet.
Originally posted on my medium account, a bit polished before posting it here.