Core Data is much more than a database and this becomes clear when you start working with relationships. Relationships in Core Data are powerful because the framework does a lot of the heavy lifting for you.

Delete Rules

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 notes relationship of the Category entity and open the Data Model Inspector on the right.

Every relationship has a delete rule.

By default, the delete rule of a relationship is set to Nullify. Core Data supports four delete rules:

  • No Action
  • Nullify
  • Cascade
  • and Deny

No Action

If the delete rule of a relationship is set to No Action, nothing happens when the owner of the relationship is deleted. Let me illustrate this with an example. We have a category record that contains several note records. If the category record is deleted, the note records are not notified of this event. Every note record believes that it's still associated with the deleted category.

No Action Delete Rule

I've never had a need to use this delete rule. In most situations, you want to take some action when a record is deleted. And that's 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 owner of the relationship is deleted. If a category has several notes and the category is deleted, the relationship pointing from the notes to the category is nullified. This is the default delete rule and the delete rule you will find yourself using most often.

Nullify Delete Rule

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 or trickles down to the user records it is linked to.

Cascade Delete Rule

If you're dealing with a many-to-many relationship, though, this is often not what you want. If a tag with several notes is deleted, you don't want to delete every note linked to the tag. The notes could be associated with other tags, for example.

Deny

Deny is another powerful and useful pattern. It's 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 record is linked to several user records, then the account record can only be deleted if it's no longer tied to any user records. This configuration prevents the scenario in which users are no longer associated with an account.

Deny Delete Rule

Evaluating the Data Model

With the above in mind, you may be wondering if we need to change the delete rule of any of the relationships defined in the data model. Let's take a look. The default delete rule of a relationship is Nullify, which means every relationship we defined has its delete rule set to Nullify. Is that what we want?

Let's start with the relationships of the Note and Category entities. If the user deletes a note, should the application automatically delete the note's category? No. This means that Nullify is the correct choice for the category relationship of the Note entity.

The inverse is also true. If the user deletes a category, should the application automatically delete every note linked to that category? No. That's not the behavior the user expects. Nullify is the delete rule we stick with.

The same logic applies to the relationships of the Note and Tag entities. Deleting a note or a tag shouldn't result in the deletion of any records linked to the deleted record. We stick with Nullify for both relationships.

Another Scenario

But this isn't the only possible configuration. Let's assume a note must have a category. In that scenario, we mark the category relationship of the Note entity as required by unchecking the Optional checkbox in the Data Model Inspector. What's different about that scenario? What would or should happen if a category is deleted?

Nothing changes if the user deletes a note. The delete rule of the category relationship should be set to Nullify. But what happens if the user deletes a category and the notes relationship is set to Nullify? Every note is required to have a category. To avoid that notes end up without a category, we could set the delete rule to Deny to make sure a category with one or more notes cannot be deleted.

While that is a possible solution, it would most likely frustrate the user because it would result in an unpleasant and odd user experience. We could offer the user the option to delete every note linked to the category when the category is deleted, but that too would be an odd workaround.

With this example, I want to emphasize the importance of spending time thinking about the data model of your Core Data application. Create an outline and list the possible scenarios the user might encounter. It's easy to make changes to the data model during development. It's hard and a pain to make changes when your application is shipped and in the hands of hundreds or thousands of users.

More Configuration

If you take a closer look at the Data Model Inspector, you can see that Xcode offers you a few more options to configure relationships. We can, for example, define validation rules. We could, for example, define a minimum and maximum number of tags for a note record.

Configuring Relationships

There are also a number of more advanced configuration options we won't cover in this series, such as indexing and versioning options. Core Data is a very powerful framework and it has gained this power over more than ten years. It's a proven solution with many, many possibilities.