Core Data is great at managing relationships. In this tutorial, we explore the data model and take a close look at relationships.

Setting Up the Project

Open Xcode and create a new project based on the Single View Application template. Name the project Library and don't forget to check the Use Core Data checkbox during project setup.

Data Model, Entities, and Relationships | Setting Up the Project

Before we can start working with relationships, we need to add a few entities to the data model. Open Library.xcdatamodeld and add three entities, Library, Author, and Book.

The Library entity has two attributes, name and location, both of type String. The Author entity also has two attributes, firstName and lastName, both of type String. The Book entity has three attributes, title of type String, publicationDate of type Date, and pages of type Integer 16. This is what the data model should look like in the data model graph.

Data Model, Entities, and Relationships | Populating the Data Model

Planning Ahead

A library contains books and books are written by authors. That's the idea underlying the data model we're creating. This implies that the Author entity is tied to the Book entity. The Library and Book entities are also linked.

But this is only one possible solution. We can also say that a library contains the books of authors and that authors have written books. Do you see the difference? In that scenario, the Library entity has a relationship with the Author entity, not the Book entity.

When working with data models, it is critical to spend time planning and thinking what the data model should look like. Once you have decided on the data model, it is often expensive to make drastic changes to it. We learn more about what that means for Core Data when we discuss migrations.

When working with data models, it is critical to spend time planning and thinking what the data model should look like.

Relationships

To-One Relationships

An entity has attributes and relationships. Let me show you how to define relationships in the data model.

A book belongs to a library. This means that we need to create a relationship that links a book to a library. Open Library.xcdatamodeld and switch to the editor's table style. Select the Book entity and click the plus button at the bottom of the Relationships table to add a relationship to the entity. Set Relationship to library and Destination to the Library entity. Leave Inverse empty for now.

Data Model, Entities, and Relationships | Adding a To-One Relationship

Switch to the editor's graph style to see the visual representation of the relationship we defined.

Data Model, Entities, and Relationships | Adding a To-One Relationship

Before we move on, there are a number of details we need to discuss. The relationship we added is a to-one relationship, a book can belong to only one library. This is visualized in the data model graph by the single arrow pointing from the Book entity to the Library entity.

Note that the arrow points from Book to Library. There is no arrow pointing back from Library to Book. There is no inverse relationship because we haven't defined one yet. This implies that the library the book belongs to does not know that the book belongs to the library. That is not what we want, though. A library should know what books it contains. Right?

Inverse Relationships

Switch to the editor's table style and select the Library entity. Add a relationship and name it books, plural. Set Destination to Book and set Inverse to library. By setting the inverse relationship to library, the inverse relationship of the books relationship is automatically set to the library relationship of the Book entity.

Data Model, Entities, and Relationships | Adding an Inverse Relationship

Switch to the data model graph to see what that looks like. The connection between Library and Book contains arrows pointing to and from each entity.

Data Model, Entities, and Relationships | Adding an Inverse Relationship

Switch back to the editor's table style and select the Book entity. Note that the inverse relationship of the library relationship is automatically set to books because we set the inverse relationship of the books relationship to library. Core Data is clever enough to take care of that for us.

To-Many Relationships

Both library and books are to-one relationships. This severely limits the data model. A library with only one book isn't much of a library. Fortunately, this is easy to fix. Select the books relationship of the Library entity in the editor's table style. Open the Data Model Inspector in the Utilities pane on the right to see the details of the relationship.

In the Data Model Inspector, you can modify the relationship's destination and inverse relationship. You can also modify the relationship's type or cardinality. Core Data supports To-One and To-Many relationships. Set Type to To-Many.

Data Model, Entities, and Relationships | Adding a To-Many Relationship

Switch back to the data model graph to see what has changed. The relationship from Library to Book now has two arrows, indicating that books is a to-many relationship.

Data Model, Entities, and Relationships | Adding a To-Many Relationship

Many-To-Many Relationships

Wait a second. Can a book only be in one library? While that may be true for exceptionally rare books, most books can be found in more than one library. We need to turn the library relationship into a to-many relationship. Select the library relationship of the Book entity in the editor's table style and set Type to To-Many in the Data Model Inspector.

Naming conventions are very important, especially if you are working in a team. Even though the library relationship is now a to-many relationship, the name of the relationship doesn't reflect this change. Update the name of the relationship to libraries. That makes more sense. Developers new to the project will immediately understand that a book can belong to multiple libraries.

This is what the data model graph looks like after the changes. The relationship that links the Library and Book entities is now a many-to-many relationship.

Data Model, Entities, and Relationships | Adding a Many-To-Many Relationship

Delete Rules

Core Data is much more than a database and this becomes obvious when working with relationships. Core Data Relationships are powerful because the framework does a lot of the heavy lifting for you. We further explore and use delete rules in Mastering Core Data With Swift 3 to build Notes.

Delete rules are one of the conveniences that make working with Core Data great. Every relationship has a delete rule. It defines what happens when the record that owns the relationship is deleted. Let me explain what that means.

Select the books relationship of the Library entity and open the Data Model Inspector on the right. By default, the delete rule of a relationship is set to nullify. Core Data supports four delete rules:

  • No Action
  • Nullify
  • Cascade
  • Deny

No Action

If the delete rule of a relationship is set to No Action, nothing happens. Let me illustrate this with an example. We have a library record that contains several book records. If the library record is deleted, the book records are not notified of this event. Every book record thinks it is still associated with the deleted library.

I have never had a need to use this delete rule. In most situations, you want to take some action when a record is deleted. That is where the other delete rules come into play.

Nullify

If the delete rule of a relationship is set to Nullify, the destination of the relationship is nullified when the record is deleted. If a library has several books and the library is deleted, the relationship pointing from the books to the library is nullified. This is the default delete rule and the delete rule you will find yourself using most often.

Cascade

Cascade is useful if the data model includes one or more dependencies. For example, if an account record has a relationship to one or more user records, it may be desirable to delete every user if the account the user belongs to is deleted. In other words, the deletion of the account record cascades to the user records it is linked to.

If you are dealing with a many-to-many relationship, though, this is most likely not what you want. If a library with several books is deleted, you don't want to delete every book in the library. The books could be associated with other libraries, for example.

Deny

Deny is another powerful and useful pattern. It is the opposite of the Cascade delete rule. Instead of cascading the deletion of a record, it prevents the deletion of a record. For example, if an account is associated with several users, the account can only be deleted if it is no longer tied to any users. This configuration prevents the scenario in which users are no longer associated with an account.

Exercise

We haven't created any relationships for the Author entity yet. Let me give you an exercise to put what you have learned into practice. I'll give you two hints to help you set up the relationships.

Hint 1

Every author has written one or more books and a book can have multiple authors. This should help you determine the cardinality (to-one, to-many, many-to-many) of the relationships.

Hint 2

If a book is deleted, the author should not be deleted unless no other books are associated with the author. When an author is deleted, books associated with the author should only be deleted if no other author is linked to the book.

You can find the solution of this exercise on GitHub. Let me know if you have any questions or need help solving this puzzle.

Now that you know what Core Data is and how the Core Data stack is set up, it's time to write some code. If you're serious about Core Data, check out Mastering Core Data With Swift. We build an application that is powered by Core Data and you learn everything you need to know to use Core Data in your own projects.