In iOS 17, Apple launched a brand new framework referred to as SwiftData to switch the Core Knowledge framework. Earlier, we now have written an introductory tutorial about SwiftData and confirmed you pair SwiftData with SwiftUI.
Whereas there are quite a few studying sources out there for utilizing SwiftData with SwiftUI, some readers have talked about that discovering complete guides for integrating SwiftData into UIKit apps could be difficult. On this tutorial, we are going to delve into the method of leveraging the capabilities of SwiftData throughout the UIKit framework.
A Fast Introduction about SwiftData
To start out off, let’s take a quick tour of the SwiftData framework. It’s essential to grasp that SwiftData shouldn’t be mistaken for a database itself. As an alternative, it’s a framework constructed upon Core Knowledge, particularly developed to help builders in successfully managing and interacting with knowledge saved persistently. Whereas the default persistent retailer utilized by iOS is usually the SQLite database, it’s value noting that persistent shops can are available in numerous varieties. As an example, Core Knowledge will also be employed to handle knowledge saved in an area file, corresponding to an XML file. This flexibility permits builders to decide on probably the most appropriate persistent retailer for his or her particular necessities.
Whether or not you go for Core Knowledge or the SwiftData framework, each instruments goal to simplify the intricacies of the underlying persistent retailer for builders. Take the SQLite database, for instance. With SwiftData, there’s no must concern your self with establishing database connections or delving into SQL queries to retrieve knowledge data. As an alternative, builders can deal with using user-friendly APIs and Swift Macros, corresponding to @Mannequin
, to effectively handle knowledge inside their purposes. This abstraction permits for a extra streamlined and intuitive knowledge administration expertise.

In case you have used Core Knowledge earlier than, chances are you’ll keep in mind that you must create a knowledge mannequin (with a file extension .xcdatamodeld
) utilizing a knowledge mannequin editor for knowledge persistence. With the discharge of SwiftData, you not want to try this. SwiftData streamlines the entire course of with macros, one other new Swift function in iOS 17. Say, for instance, you already outline a mannequin class for Track as follows:
class Track {
var title: String
var artist: String
var album: String
var style: String
var ranking: Double
}
To make use of SwiftData, the brand new @Mannequin
macro is the important thing for storing persistent knowledge utilizing SwiftUI. As an alternative of constructing the information mannequin with mannequin editor, SwiftData simply requires you to annotate the mannequin class with the @Mannequin
macro like this:
@Mannequin class Track {
var title: String
var artist: String
var album: String
var style: String
var ranking: Double
}
That is the way you outline the schema of the information mannequin in code. With this easy key phrase, SwiftData routinely permits persistence for the information class and provides different knowledge administration functionalities corresponding to iCloud sync. Attributes are inferred from properties and it helps primary worth varieties corresponding to Int
and String
.
SwiftData permits you to customise how your schema is constructed utilizing property metadata. You possibly can add uniqueness constraints through the use of the @Attribute
annotation, and delete propagation guidelines with the @Relationship
annotation. If there are particular properties you do not need included, you should use the @Transient
macro to inform SwiftData to exclude them. Right here is an instance:
@Mannequin class Album {
@Attribute(.distinctive) var title: String
var artist: String
var style: String
// The cascade relationship instructs SwiftData to delete all
// songs when the album is deleted.
@Attribute(.cascade) var songs: [Song]? = []
}
To drive the information persistent operations, there are two key objects of SwiftData that you need to be aware of: ModelContainer
and ModelContext
. The ModelContainer
serves because the persistent backend in your mannequin varieties. To create a ModelContaine
r, you merely must instantiate an occasion of it.
// Primary
let container = attempt ModelContainer(for: [Song.self, Album.self])
// With configuration
let container = attempt ModelContainer(for: [Song.self, Album.self],
configurations: ModelConfiguration(url: URL("path"))))
In UIKit, you possibly can instantiate the context for a given mannequin containers like this:
let context = ModelContext(modelContainer)
With the context, you’re able to fetch knowledge. You should utilize the brand new #Predicate macro to construct predicates. Right here is an instance:
// Specify all of the songs whose style is "Pop"
let songPredicate = #Predicate { $0.style == "pop" }
When you outline the standards for fetching, you should use the FetchDescriptor
and inform the mannequin context to fetch the information.
let descriptor = FetchDescriptor(predicate: songPredicate)
let songs = attempt context.fetch(descriptor)
To insert merchandise within the persistent retailer, you possibly can name the insert methodology of the mannequin context and cross it the mannequin objects to insert.
modelContext.insert(tune)
Equally, you possibly can delete the merchandise by way of the mannequin context like this:
modelContext.delete(tune)
This serves as a quick introduction to SwiftData. Should you’re nonetheless feeling uncertain about make the most of SwiftData, there’s no want to fret. You’ll achieve a transparent understanding of its utilization as we’ll construct a easy To-do app utilizing UIKit and SwiftData.
Constructing a Easy To-do App with SwiftData and UIKit
I’ve already developed a primary to-do app utilizing UIKit. Nevertheless, the present implementation solely shops the to-do gadgets in reminiscence, which suggests the information just isn’t persistent. With a purpose to handle this limitation, our subsequent step is to switch the app and swap from utilizing in-memory arrays to leveraging the facility of SwiftData for storing the to-do gadgets in a database. This enhancement will be certain that the to-do gadgets are saved persistently, permitting customers to entry them even after closing the app.

For demo goal, the present model of this app doesn’t present the performance for customers so as to add their very own to-do gadgets. As an alternative, customers can solely add a random to-do merchandise by tapping the “+” button. Nevertheless, customers can nonetheless modify the standing of the present merchandise and delete it by swiping.
Utilizing @Mannequin for the mannequin class
The in-memory model of the app already defines a struct for ToDoItem
:
struct ToDoItem: Identifiable, Hashable {
var id: UUID
var title: String
var isComplete: Bool
init(id: UUID = UUID(), title: String = "", isComplete: Bool = false) {
self.id = id
self.title = title
self.isComplete = isComplete
}
}
To make use of SwiftData, we will convert this struct
to class
and annotate it with the @Mannequin
macro like this:
import SwiftData
@Mannequin class ToDoItem: Identifiable, Hashable {
var id: UUID
var title: String
var isComplete: Bool
init(id: UUID = UUID(), title: String = "", isComplete: Bool = false) {
self.id = id
self.title = title
self.isComplete = isComplete
}
}
As you possibly can see, the one factor that we have to do to make a category work with SwiftData is to prefix it with @Mannequin
. SwiftData then routinely permits persistence for the information class.
Saving To-Do Gadgets into Database
Within the demo app, we now have the ToDoTableViewController
class to deal with the rendering of the to-do desk view, in addition to, the random creation of the to-do gadgets. To handle knowledge with SwiftData, we first create a variable to carry the mannequin container:
var container: ModelContainer?
Within the viewDidLoad
methodology, we will add the next line of code to instantiate the mannequin container:
container = attempt? ModelContainer(for: ToDoItem.self)
For including a random to-do merchandise, the demo app already had a way named addToDoItem
:
@IBAction func addToDoItem(sender: UIBarButtonItem) {
todoItems.append(generateRandomTodoItem())
updateSnapshot(animatingChange: true)
}
We referred to as up the generateRandomTodoItem
methodology to get a to-do merchandise and append it to the todoItems
array. Then we name up the updateSnapshot
methodology to replace the desk view.
With a purpose to save the to-do merchandise completely, we will substitute the code like this:
@IBAction func addToDoItem(sender: UIBarButtonItem) {
container?.mainContext.insert(generateRandomTodoItem())
fetchToDoItems()
}
As an alternative of merely including the to-do merchandise to the array, we make the most of the insert
methodology of the container’s context to save lots of the merchandise into the interior database.
Fetching Knowledge from Database
The implementation of the fetchToDoItems
methodology is pending for the time being. To retrieve knowledge from the database, we have to create an occasion of FetchDescriptor
. This enables us to specify the information sort we wish to retrieve and outline any particular search standards if obligatory. By using the FetchDescriptor
, we will successfully retrieve the specified knowledge from the database. After establishing the fetch descriptor object, we will proceed to name the fetch
methodology of the container’s context and supply the descriptor as an argument. SwiftData will then make the most of this data to retrieve the to-do gadgets accordingly from the database.
Insert the next code snippet to create the fetchToDoItems
methodology:
func fetchToDoItems() {
let descriptor = FetchDescriptor()
todoItems = (attempt? container?.mainContext.fetch(descriptor)) ?? []
updateSnapshot()
}
As soon as we retrieve all of the to-do gadgets, we have to invoke the updateSnapshot
methodology to replace the desk view.
Deleting Knowledge from Database
Within the pattern app, we now have a swipe motion for deleting a row merchandise like this:
let deleteAction = UIContextualAction(type: .harmful, title: "Delete") { (motion, sourceView, completionHandler) in
var snapshot = self.dataSource.snapshot()
snapshot.deleteItems([todoItem])
self.dataSource.apply(snapshot, animatingDifferences: true)
// Name completion handler to dismiss the motion button
completionHandler(true)
}
For now, it solely removes a to-do merchandise from the desk view however not the database. To fully delete the merchandise from database, we have to insert a line of code within the closure:
self.container?.mainContext.delete(todoItem)
By calling the delete
methodology and offering the related merchandise, SwiftData will maintain eradicating the required merchandise from the database, guaranteeing that it’s not continued in our app’s knowledge storage.
That is how we migrate the to-do app from utilizing in-memory storage to database utilizing SwiftData.
Abstract
By following the steps outlined above, we efficiently migrated the to-do app from utilizing in-memory storage to using a database with the assistance of SwiftData. As demonstrated, the mix of the @Mannequin
macro and SwiftData framework simplifies the method of incorporating a database into an app.
We hope that by means of this tutorial, you now possess a clearer understanding of combine SwiftData right into a SwiftUI challenge and carry out important CRUD (Create, Learn, Replace, Delete) operations. Apple has invested vital effort in making persistent knowledge administration and knowledge modeling extra accessible for Swift builders, together with newcomers to the language.
With SwiftData, you could have a robust software at your disposal to deal with knowledge storage and retrieval effectively. We encourage you to discover additional and leverage the capabilities of SwiftData to reinforce your app growth journey.