Greetings!

It’s been a while I haven’t written anything, I was out of topics to write on.
Lately I have been working on app at my work place which strongly depends on Core Data. Which gave me an idea to write on Relationships in Core Data.
Without any further delay, Let’s get started.

You can clone the Starter Project app called BookBase, so it may help you to follow along. After cloning the app, let’s open the BookBase.xcdatamodeld.

We are going to create two Entities here, Books and an entity named Authors, then first we will understand how One-Many Relationship can be established between the two entities, then we will look into Many-Many Relationship. Cool thing about Xcode is that now it generates classes for Entities on its own.

One-Many Relationship

Click on Add Entity button and create two entities one Books and the other one named Authors. Now select the entity Books and add an attribute called bookTitle of  type String and set the destination to Authors. After click on + on the Relationships section and create a relationship with named hasAuthors, uncheck the optional check because a Book will always has Author, then select the relationship and from the File inspector select the last icon and set the Type of relationship from To One to To Many.  As shown in the picture below,


You have just created your first One-Many relation. We’ll go into implementations later, let’s move on to making it a Many-Many relationship.

Many-Many Relationship

A Book can have multiple Authors and an Author can have multiple Books. Inside your Authors’ entity create an attribute authorName. In your Relationship section create a new relation with name hasBooks and set the destination to Books. Change the Inverse Relationship to hasAuthors from No Inverse, and at last make the type of the relationship To Many from the File Inspector. Inverse relation ensures that the entity from which a to Many relation has been made towards the other entity also acknowledges that it has a relation to that particular entity to maintain data integrity.

You have successfully created a Many-Many Relationship between the two entities. Let’s dive in to some code now.

We’ll create a class that will manage the adding and searching the Books from Core Data, let’s name it CoreDataManager. We’ll also create properties that will hold the fetched Books and Authors, a property that manage the context and a function that saves the context as displayed in the class below.

First we’ll create a function which will fetch all the records from CoreData and call it on the time when object of CoreDataManager is being created.

After setting these things up, we’ll create a function which will save Book title and Author name to the Core Data. But first let’s have a look at the UI.

The UI consists of two TextFields for entering Book’s title and  the second one is for the Author name, and three buttons to Add, to Search, and to Refresh.

Insertion in Core Data

So we’ve seen how the UI is, now we’ll get back to writing that function which will help us to insert data in Core Data.

So how this function works?, First it checks if the passed Book already exist or not, if Yes, it doesn’t do anything, if No, then it creates an object of type Books,  then it checks if the passed in Author name is already in the CoreData if No? then creates an Authors object, if user passes in multiple Authors separated by a “,” then that logic is also handled there, if an Author is already in the CoreData than the same object of Authors is used to create a new object of Books, a completion returns true if Book is saved successfully otherwise a false.

Fetching from Core Data

Let’s move on to writing functions for searching Books by either Author name or Book title.

What these function does is filter the ManagedObject ([Books] or [Authors]) w.r.t to arguments provided i.e. (Book title or Author name), after getting the desired Books or Author, it fetches the respective relation, and takes out the required information from it, which would be a Books and Authors. {Please don’t mind the excessive use of closure functions in the search, but I feel more comfortable using them. :)}

Just to make things look tidy.

Setting up the Controller

Our work in this class is done here. It’s time to move on to your ViewController. In your controller create two properties as:

CoreDataManager object is for manipulating the data and other one is for displaying the searched results inside the tableview.

In your Add button’s @IBAction i.e addToCoreData write the following code:

Inside the @IBAction of Search, write this:

Change your TableView’s DataSource to look like this:

In the end, in your Refresh button’s action:

Build and Run

Now, Its time to build and run the app.

 

And add some books in it. After that try and search. Let’s search by passing in the name of the Author in the textfield.

 

You can try and search with a Book name as well.

Questions?

So this was all there is to it for now, and source code is available here.
If you have any questions please leave a comment below.

Sayonara!

Share:

administrator

Aaqib is an enthusiastic programmer with the love of Swift and anything that looks like Swift i.e Kotlin. He loves writing code in Swift, and exploring new technology and platforms. He likes to listen to old music. When he is not writing code, he's probably spend his time watching movies, tv-shows or anime, or either doing some research for writing the next article. He started Kode Snippets in 2015.

2 Comments

  • Sajad, July 11, 2018 @ 6:19 pm Reply

    Hi Aqib,
    Fetching all the entities and storing them in local var this way, does it cause to realize all the objects? or will those be faults until an item is fetched from the array.
    And wouldn’t it be better to user FetchRequest for searching the books or author? Even if they are faults , don’t you think that would be better architecture? as this is a database app.

    • Aaqib Hussain, July 21, 2018 @ 10:18 pm Reply

      Hi Sajid!
      I think it’s based on what your needs are. Let’s say if this app showed the list of all the books on start up I would eventually be fetching all the records. So basically its just your practice. I think they will faults until an item is accessed from the array.
      It really depends on how one feels comfortable using something, I feel filters more easy to use and flexible. Since we already have all the fetched records in an array, why create a fetch request and go through all that again? I don’t see any point of that in this scenario. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *