Category: Core Data

Storing an Array of Custom Structs in Core Data

A common question I see online about Core Data involves storing arrays. You have an array of a custom struct or class that you want to store in Core Data. Your initial instinct is to create an attribute for the array in your Core Data entity. But you discover that none of the available attribute types work. How do you store the array?

The Solution: Create a To-Many Relationship

There are two steps to storing an array of a custom struct or class in Core Data. The first step is to create a Core Data entity for your custom struct or class.

The second step is to add a to-many relationship in the Core Data entity where you want to store the array. The destination for the relationship is the entity you created for the custom struct or class. The to-many relationship holds the array items. Saving the main entity, the entity where you want to store the array, will save the array items.

Keep in mind that Core Data uses sets to store to-many relationships instead of arrays. Each item that Core Data stores must be unique. Each element of a set must also be unique, which is why Core Data uses sets.

A Simple Example

Let’s look at a simple example of creating a to-many relationship. Suppose you have a Note entity and you want to store a list of each note’s tags. Start by creating a Tag entity and adding the attributes you want a tag to have.

After creating the Tag entity, select the Note entity in Xcode’s data model editor and add a relationship. Name the relationship tags. Choose Tag as the destination.

When you select the relationship, the data model inspector should be visible on the right side of the project window. Choose To Many from the Type menu. The relationship must be to-many to store a set (array) of items.

SetToManyRelationship

Select the Ordered checkbox if you need the relationship items to be in a specific order.

After creating the relationship each note has a list of tags. With the right controls in the app, you can add and remove tags. When you save a note Core Data also saves the tags.

Core Data Code Generation

Starting with Xcode 8, you can let Xcode generate the code for your Core Data entities. Access an entity’s code generation options by selecting the entity and opening the data model inspector.

Xcode8CoreDataCodeGenMenu

The Codegen menu is where you specify the code generation for the entity. There are three code generation options.

  • Choosing Manual/None tells Xcode not to generate code for the entity. You must create the class for the entity by creating a new file or by choosing Editor > Create NSManagedObject Subclass.
  • Choosing Class Definition tells Xcode to create the entity’s class files when you build the project.
  • Choosing Category/Extension tells Xcode to create a Swift class extension for the entity when you build the project. The class extension has accessors for the entity’s attributes.

Where are the Source Code Files?

If you choose Class Definition or Category/Extension from the Codegen menu, you’ll notice there are no source code files for the entities in the project navigator. Where are the files?

The source code files are in the project’s derived data location. You’re not meant to access and edit the source code files Xcode creates for your Core Data entities. The point of Xcode creating the files is to automatically update the files when you make changes to the data model.

What do you do if you want to add methods to your Core Data entities? Create Swift class extension files for your entities and add your methods there.

Duplicate Classes

When you create a new Xcode project that uses Core Data, the code generation is initially set to Class Definition. If you manually add class files for your entities, your project won’t build because you have two versions of each class, the one you manually created and the one Xcode creates. This issue can be tough to find because you can’t see the Xcode-created class files in the project navigator.

There are two ways to deal with the duplicate class problem. The first way is to remove the class files you added to the project and let Xcode create the classes for you. The second way is to switch to manual code generation by choosing Manual/None from the Codegen menu.

Which Code Generation Option Should You Choose?

Choose manual code generation if you’re using version control in your project. By writing the entity’s code yourself, you can track the changes in your version control system and go back if you make a mistake.

Choose the Class Definition code generation option if you don’t want to worry about keeping the data model and code in sync. When you make changes to the data model, you don’t have to worry about updating the code if you choose Class Definition. Xcode updates the code for you.

Choose the Category/Extension code generation option if you need more control over the class hierarchy. If you choose the Class Definition code generation option or choose Editor > Create NSManagedObject Subclass to generate your classes manually, Xcode assumes the entity and class hierarchies are the same. If you want a different class hierarchy for your data model, choose the Category/Extension code generation option.