CoreData — the easy way
In this article, I’ll explain how to get started with CoreData with SwiftUI. CoreData isn’t as difficult as it was years ago.
First, create a new Xcode project called “UserList”, check CoreData and we’ll use SwiftUI. Save the project at the location of your choice.
In this case we use partly the provided Swift files and partly the provided code. First we look at the UserList.xcdatamodeld and change the entries.
We create / change the entity to User with an attribute name which will map the type String. In addition, we select the attribute as above and uncheck Optional. Because the name is always present with User and is not optional.
Next we delete the Persistence.swift file as we are creating our own Swift file. We now create a new Swift file and name it -> CoreDataStack.swift.
Add the code below to the CoreDataStack.swift file.
import CoreData
public class PersistentContainer: NSPersistentContainer {}
public class CoreDataStack {
public let persistentContainer: NSPersistentContainer
public init() {
persistentContainer = PersistentContainer(name: "UserList")
persistentContainer.loadPersistentStores(completionHandler: { description, error in
if let error = error {
fatalError("Core Data store failed to load with error: \(error)")
}
})
}
}
public extension CoreDataStack {
func saveUser(named name: String) {
let user = User(context: persistentContainer.viewContext)
user.name = name
do {
try persistentContainer.viewContext.save()
print("User saved succesfully")
} catch {
persistentContainer.viewContext.rollback()
print("Failed to save movie: \(error)")
}
}
}
public extension CoreDataStack {
func getAllUsers() -> [User] {
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
do {
return try persistentContainer.viewContext.fetch(fetchRequest)
} catch {
print("Failed to fetch movies: \(error)")
return []
}
}
}
public extension CoreDataStack {
func deleteUser(_ user: User) {
persistentContainer.viewContext.delete(user)
do {
try persistentContainer.viewContext.save()
} catch {
persistentContainer.viewContext.rollback()
print("Failed to save context: \(error)")
}
}
func updateUser(_ user: User) {
do {
try persistentContainer.viewContext.save()
} catch {
persistentContainer.viewContext.rollback()
print("Failed to save context: \(error)")
}
}
}
First we create a class and initialize the data model. Then we have three extensions in which we save, call up or delete the user. The user is then synchronized with the data model.
We have to make another change in the UserListApp.swift file in order to make our CoreDataStack available in SwiftUI.
import SwiftUI
@main
struct UserListApp: App {
var body: some Scene {
WindowGroup {
ContentView(coreDataStack: CoreDataStack())
}
}
}
Here we call the CoreDateStack and link the stack with the ContentView. In ContentView.swift I have the code as follows:
import SwiftUI
import CoreData
struct ContentView: View {
let coreDataStack: CoreDataStack
@State var userName = ""
@State var users : [User] = []
var body: some View {
VStack {
Text("Add a user")
.font(.title)
.padding()
HStack {
TextField("Type user name", text: $userName)
Button("Save user") {
coreDataStack.saveUser(named: userName)
users = coreDataStack.getAllUsers()
}
Spacer()
}.padding()
List {
ForEach(users) { (user: User) in
Text(user.name ?? "")
}.onDelete { rows in
for row in rows {
let user = users[row]
coreDataStack.deleteUser(user)
}
users.remove(atOffsets: rows)
}
}.onAppear {
users = coreDataStack.getAllUsers()
}
}.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(coreDataStack: CoreDataStack())
}
}
In ContenView we create the design of the app, there are no limits here. We also create a constant for the CoreDataStack and call its functions.
With this article I just wanted to show you how easy it is to integrate CoreData in an app. The code for this project can also be found on Github: