CoreData using Generics and the Singleton design pattern

Gianluca Annina
3 min readFeb 7, 2023

--

Do you need to store information locally on your device? If the answer is affirmative and the data are too big for UserDefault then you will probably need to use CoreData.

What is, then, the most efficient way to use CoreData? Let’s take a look at what Xcode suggests us to do when creating a new project importing CoreData.

Checking this box will create a whole project ready to be used with examples of how to use CoreData with different useful functions already implemented.

Most important it will generate the “Data Model” file and the “PersistenceController” struct. Let's take a deeper look at this struct.

As it’s possible to notice the “PersistenceController” retrieves the information of the container and its context, then it uses the “@EnvironmentObject” to pass the retrieved context to every View.

This kind of approach doesn’t take full advantage of the Singleton design pattern and makes the code messy.

A better way to use CoreData

A better approach would be to use the “PersistenceController” to also handle the different operations, maybe using different extensions of the struct to keep the different files tidier.

Initially, the “PersistenceController” will be simple and without any function except for the private initialiser.

Now we can create the functions that implement the generics, in detail “fetch” and “delete”

The “fetch” function is simple, it takes as a parameter the name of the entity and the type, using them it retrieves all the values stored in the table.

Be careful: when using the generics in this way since you always have to declare the type of your variable, otherwise the function will not understand from what table you need to fetch data.

The “delete” function is even simpler and just needs, as a parameter, the element you want to delete.

The “saveContext” function it’s used to save the changes made when deleting/adding/editing an object.

Unfortunately, it’s not possible to completely integrate the generics mechanism with the creation of a new element. The basic function is the following:

Now you are probably asking yourself: “What are Product and the copyInEntity functions?”

Product is the struct that encapsulates all the pieces of information retrieved from CoreData and handles them inside the view.

It is declared this way:

Inside the struct are defined two functions that help to exchange data between the swift object and the CoreData object:

  • the custom init takes as a parameter a CoreData object and assigns all the values to the swift one;
  • the copyInEntity does the exact opposite, assigning to a CoreData object all the values of the swift one.

These two functions are useful in order to clean the code and handle the code in a faster way.

If you want to check the original project here is the GitHub link:
https://github.com/SidusProxy/CoreDataTutorial

--

--